Nice TWiki > Dev > WebHome (book view) TWiki webs:
Dev | Doc | Main | TWiki | Sandbox
Dev . { Changes | Index | Search | Go }
Search: \.*

Topics in Dev web: Changed: GMT Changed by:

AddingConstness  

21 Nov 2003 - 07:40 - r1.4   BrianSlesinsky

On a longer term(post 1.0) Nice might get a const keyword. Anyone who's is interested in writing a proposal should look at this proposal for java: http://david.tribble.com/text/javaconst.html

It's a very good starting point in my opinion.

An extension to Java exists that add constness: http://pag.lcs.mit.edu/constjava/

-- ArjanB

How would this be different from let?

-- IsaacGouy - 17 Sep 2003

When using let or final in java you can't change the reference. And const is like in c++ that the object that is referenced may not be changed.

-- ArjanB

I never much liked "const" as it exists in C++. The problem is that an object might appear to be mutable or immuable depending on where you are in the code. So a "const" object might change due to action somewhere else in the program.

Much better to have true immutable objects. Perhaps mutable and immutable versions of the same type, similar to !T and ?T.

Final instance variables in Java provide finer control since you can make an object partially immutable.

-- BrianSlesinsky - 21 Nov 2003

 


AnnouncingNewReleases  

29 Jul 2004 - 15:28 - r1.6   DanielBonniot

How and where to announce new releases?

The release itself is done on sourceforge. It includes release notes and the changelog (copy-pasted from the changelog in CVS). An item automatically appears under http://sourceforge.net/new/, but I don't think this will reach many people, given the number of releases every day. It is an option to write a news item on the Nice project: a few are selected by people and put on the main website. There is also the Java foundry, where news items can be submitted.

Nice has also a project page on freshmeat and in the GNU directory.

Lambda the Ultimate is a good place to announce Nice (major releases only), or to discuss a new feature. Is there a LtU regular who would like to be in charge of this?

Newsgroups: anybody using these? (comp.lang.???).

comp.lang.java.advocacy -- IsaacGouy - 27 Aug 2003

Other places?

-- DanielBonniot - 30 May 2003

Sample presentation text for Nice

This can be used, after possible editing to adapt it to the audience, to give a short presentation of Nice:

Nice is a new object-oriented programming language based on Java. It incorporates features from functional programming, and puts into practice state-of-the-art results from academic research. Among the advanced features: parametric types, anonymous functions, multi-methods, tuples, optional parameters to methods, design by contract, detection of many errors during compilation (in particular, concerning casts and null references). This results in more expressivity, modularity, and type safety.

Changes in each major version from the previous one

0.8

Added various missing Java constructs: super, synchronized statements, Java 1.4 style assertions, and Java 1.5-compatible generic classes. Also implemented Design By Contract features: pre- and post-conditions for methods. Method dispatch can be done on boolean and integer values.

 


AnonymousExceptionHandling  

21 Oct 2004 - 12:01 - NEW   ImamTashdidUlAlam

I was just wondering, when Nice interacts heavily with Java, the resultant code contains too many curly braces which are not nice at all, as exceptions must be handled. Most of the time, however, we know specifically what the exception ought to be. Why not have a perl like syntax for handing those?

BufferedReader? br = new BufferedReader?(new FileReader?(file)) || return false;

-- ImamTashdidUlAlam - 21 Oct 2004

 


AutomatedTests  

22 Jun 2003 - 09:36 - NEW   DanielBonniot

Tests are performed continuously to check that the compiler is working properly.

The results are published on the website.

The tests involve bootstraping the compiler (compiling the compiler with itself), running the testsuite, and compiling some other programs written in Nice. Here is the documentation about WritingAutomatedTests.

The tests are run on different machines, and different configurations (for instance, different JDK versions). The process of adding a new TestMachine is documented (it would be nice to have one machine using a case-insensitive file system, as found in Windows and Mac OS X).

-- DanielBonniot - 22 Jun 2003

 


BadErrorMessages  

01 Feb 2004 - 20:23 - r1.12   DanielBonniot

An overview of error messages that needs improvement.

To do

Unsatisfiable constraints

class A{}
class B extends A{}

interface I<A T>{}
class X<T | A <: T> implements I<T>{}

void foo(I<B>);

foo(@X){}

Type error in method body "foo":
mlsub.typing.TypingEx: Not satisfiable [NO MESSAGE]

Too long message when calling a method with a wrong argument.

?List<String> list = null;
list.get(1);

No possible call for get.
Arguments: (?java.util.List<java.lang.String>, nice.lang.byte)
Possibilities:
nice.lang.int get(java.util.Calendar, nice.lang.int)
java.lang.Object get(sun.reflect.FieldAccessor, ?java.lang.Object)
<K, V> V get(java.util.Dictionary<K, V>, ?java.lang.Object)
<E> E get(java.util.List<E>, nice.lang.int)
nice.lang.char get(String s, int index)
nice.lang.double get(nice.lang.Array<double>, int)
nice.lang.float get(nice.lang.Array<float>, int)
nice.lang.char get(nice.lang.Array<char>, int)
nice.lang.long get(nice.lang.Array<long>, int)
nice.lang.int get(nice.lang.Array<int>, int)
nice.lang.short get(nice.lang.Array<short>, int)
nice.lang.byte get(nice.lang.Array<byte>, int)
nice.lang.boolean get(nice.lang.Array<boolean>, int)
<Any T> T get(nice.lang.Array<T>, int)
nice.lang.boolean get(int x, int bit)
nice.lang.boolean get(long x, int bit)
<Any K, Any K0, Any V0, Any V | K <: K0, V <: ?V0> ?V0 get(java.util.Map<K, V>, K0)
<Any T, Any U> U get(Field, T)

Useless parsing exceptions

Sometime if you forget a ";" or a ")" or something else then you get a very long parse exception messages. It's not helpfull to get 20 lines of possible alternatives of wich half are multi-token alternatives.

No good example at the moment.

-- ArjanB

Here's a particularly awful example of this problem:

void main(String[] args) 
{
  String[] foo = [];
  args.foreach(String s => {
    if (true) {
      foo = null;
    } else {
      foo = foo.concat(["bar"]) //Note missing semicolon.
    }
  });  
}

This takes long enough to report a message that you're likely to think the compiler's gone into a loop, especially if it's in a real source file not just this tiny example. Finally, it produces more than 700 lines of parse alternatives, most of which look something like these:

    <IDENT> "=>" "{" "if" "(" <IDENT> ")" "{" <IDENT> "=" "null" ";" ";" ...
    <IDENT> "=>" "{" "if" "(" <IDENT> ")" "{" <IDENT> "=" "null" ";" "++" ...
    <IDENT> "=>" "{" "if" "(" <IDENT> ")" "{" <IDENT> "=" "null" ";" "--" ...
    <IDENT> "=>" "{" "if" "(" <IDENT> ")" "{" <IDENT> "=" "null" ";" "null" ...

I just tested the compiler on the real-world code that inspired this example to see how long it would actually take to report the error - I gave up after 20 minutes. :-)

-- BrynKeller - 05 May 2003

I just fixed the problem of these extreme long error messages. The parser has some difficulties with generating error messages in case of a lookahead.

But I haven't a good idea yet how to improve the normal parse exception messages.

-- ArjanB

Desugaring of ?: operator

In general, it seems like desugared code should never be shown in error messages. Only show code fragments when necessary, and only show code that actually appears in the source files.

Code:

    class A { ?Integer n; }

    void main(String [] args) {
        let a2 = new A(n: new Integer(2));
        Integer n2 = a2.n != null ? a2.n : new Integer(1);
    }

Old message:

    The value if(`!=`(a2.n(), null))
                 a2.n()
              else
                 new Integer(1)
    cannot be assigned to n2 because it might be null.

New message:

    The value a2.n != null ? a2.n : new Integer(1)
    cannot be assigned to n2 because it might be null.
or
    Attempt to assign a possibly-null value to n2

This last form could be chosen as soon as the value assigned is "big".

Recent improvements

We can keep track of recent improvements. This way, there can be a debate about the change, if somebody doesn't like it, or thinks it could be further improved.

Each entry should follow this format: code, old message, new message. To add an entry, you can copy paste the template at the bottom, and fill it in.

Null values in assignment

Code:

  List<String> l = null;

Old message:

null might be null

New message:

The value null cannot be assigned to l because it might be null.

To allow l to contain the null value, it should be declared as:
?java.util.List<java.lang.String> l

-- DanielBonniot - 30 Apr 2003

Null values in synchronization

Code:

  ?String s0 = null;
  synchronized (s0) {};

Old message:

s0 might be null

New message:

Synchonization must be done on a non-null object.
s0 might be null.

-- DanielBonniot - 30 Apr 2003

Missing arguments in constructor call - no arguments provided

Code:

class A {
 String B;
 String C = "test";
 ?String D;
}

void main(String[] args) {new A();}

Old message:

Class test.A has the following fields:
java.lang.String B, java.lang.String C = "Test", ?java.lang.String D
Please provide values for the fields, at least for those with no default value.
The syntax is:
new test.A(field1: value1, ..., fieldN: valueN) 

New message:

Fields of class test.A require initial values.
Use the following syntax:
 new test.A(B: value, D: value)

Class test.Foo has the following fields:
 java.lang.String B
 java.lang.String C = "test"
 ?java.lang.String D

BrynKeller - 30 Apr 2003

Missing arguments in constructor call - at least one argument provided

Code:

class A {
 String B;
 String C = "test";
 ?String D;
}

void main(String[] args) {new A(B: "foo");}

Old message:

Class test.A has the following fields:
java.lang.String B, java.lang.String C = "Test", ?java.lang.String D
Please provide values for the fields, at least for those with no default value.
The syntax is:
new test.A(field1: value1, ..., fieldN: valueN) 

New message:

Fields of class test.A require initial values.
These fields are missing:
 ?java.lang.String D

BrynKeller - 30 Apr 2003

template

Code:


Old message:


New message:


 


BigPictureWhatIsItGoodFor  

22 Dec 2004 - 16:33 - r1.11   MikeBeckerle

Maybe a year from now, one of the most obvious special things about Nice will turn up in releases of Java and C# ( More on Generics in the CLR ).

Reading this bold statement from the Brew project "We are currently developing Brew as a successor language to Java" made me wonder "What's the vision for Nice?".

In the same way that people seem to understand that Jython is good for glueing a program together out of Java components, what would it be that they should understand Nice is good for?

Is Nice capable of stepping up with a solution to this: The Impedance Imperative Tuples + Objects + Infosets = Too Much Stuff!

Whatever the Vision thang turns out to be, my guess is that it will give a purpose that makes decisions on language features more straightforward.

-- IsaacGouy - 18 Sep 2003

The way I see it now, Nice is a generalist programming language. So it would be more a "successor language to Java" than a niche, specialized language. There are many improvements in Nice besides genericity. I think they mostly fit under the slogan "safety, modularity, expressivity". Is this satisfactory? Is there a clearer or more striking way to put it?

-- DanielBonniot - 30 Sep 2003

"safety, modularity, expressivity"
OK can that slogan be used to drive implementation decisions?

Let's take Safety:
- instead of nicec having a -strict option, shouldn't it be strict by default?
The -strict option affects only the calling of java methods and it's not default now because of the burden to first time users. If most of the java api is given the correct nice types then -strict will probably the default.
- is there a way to 'fix' Java's silent integer overflow / modular arithmetic?
Very difficult to do without virtual machine support
- one or two folk were interested in Option Types until they saw cast(null), to them it seemed like an escape hatch that would inevitably be misused.
In a few cases cast(null) is needed. We will try to reduce them. And maybe should cast(null) not be mentioned in the manual

Modularity:
- I wish an abstract interface could be used to type fields (just a simple-minded programmer)
todo

Expressivity:
- type inference for polymorphic method vars (maybe one day)
todo
- labelled tuples?
Will they be immutable? What can you do with them that can't be done with classes or normal tuples?
- literal XML?
Can you elaborate?
OK maybe I just want to try Erik Meijer's research language ;-)
But I know why - database + program + web.

"safety, modularity, expressivity" as a slogan it's a bit too abstract, these are all good things but rather difficult to judge without doing a deal of programming. "What problem does this solve" is much easier for simple-minded programmers to understand ;-)

-- IsaacGouy? - 03 Oct 2003

Comments added in italic. -- ArjanB - 06 Oct 2003

Just found out that C# has a compiler option and keyword support for checked arithmetic -- IsaacGouy - 06 Oct 2003

- literal XML? Can you elaborate?
The motivation is laid out here: http://www.research.microsoft.com/~emeijer/Papers/XML2003/xml2003.html
-- IsaacGouy - 16 Oct 2003

I think from a big-picture standpoint, Nice is looking to be a better (easier and more reliable) way of generating .jar files than Java. But it's more of an incremental improvement than a paradigm shift.

Good IDE support (including refactoring) will be critical to get any traction at all. Back when I used Emacs, I tried out new languages all the time and didn't really give anything up by doing so. But now that I use IntelliJ?, switching to a better language doesn't look like a win if it also means using a more primitive IDE. And I expect the percentage of vi and emacs programmers will decline.

So, maybe the way to go is to design the language while working on the Eclipse plugin at the same time. Not that it should be Eclipse-specific, but language features should be designed taking the programmer's total user interface in mind.

-- BrianSlesinsky - 30 Dec 2003

Although developing an IDE/plugin at the same time could be ideal, it's not practical at the moment. A good plugin would take even more work than the compiler itself so with only 2 working on the compiler regularly it's not an option. The difficult choice between the IDEs and the limited experience of us with advanced IDEs are ohter reasons not to develop it at the same time.

How do you think that the language could be influced by a plugin?

Nice makes much more programming styles possible than Java so that we don't know anything yet about good refactorings and pratical idioms. I think we need to know more about the usage of Nice before a plugin can be useful.

-- ArjanB - 31 Dec 2003

It's true that there are still several important core language features to work on, so I cannot focus on IDEs yet. On the other hand, I agree that good IDE support will be crucial to make the language accepted and easier to develop with. We already have a core EclipsePlugin, and it would be great if one or several people interested stepped in to add more advanced features like refactoring. I'm very willing to help by providing the appropriate API in the compiler, so that the work can be focused on providing the features to the IDE user. Concerning the choice of an IDE, I think Eclipse is a good one, given it's already important user base and it's open source status. Of course it's quite fine if somebody wants to work on integration with another IDE too.

-- DanielBonniot - 26 Jan 2004

Not much activity here. But I thought I should refresh this discussion:

Big Picture: I've looked at the "languages for the JVM" and "languages for the CLR" materials on the web. It's clear that there are two trends that Nice is a response to.

Trend 1: Java/C# isn't enough. It must be complemented with something easier to use, etc. Lots of languages are responses to this, but usually these are oriented toward "scripting", that is, it is assumed that if you need to write a real or fast program you'll flop back into Java or C#. Groovy is a good example of this. Jython similarly. There are a pile of these. Often they are aimed at convenience also. Typically they don't much care about type systems.

Trend 2: Java/C# are too hard to program in. We can improve on them by creating a more modern language with type inference, etc. These are fewer in number. The languages of note here are Scala, Boo, and Nice. These languages use type inference. THey go after the expressive-power problems of Java/C#. E.g., multiple return values, type-system restrictions, run-time null-pointer exceptions, etc. There are no compromises in performance in this area. THe programs written need to be just as fast as the corresponding program written in Java/C#.

The community of people with appreciation for Trend 2 is quite a bit smaller than trend 1. The two are blurred terribly because once you add type inference you can end up with programs that are just as clean and dense as in dynamically typed languages (I've verified this with translation of Python code to Nice. If you cuddle your "else", e.g., write lines like "} else {" to keep the braces from taking up whole lines, then you get the same number of lines in Nice as you do in Python. ) So long as we don't get diluted into a "scripting" solution this blurring is good. In fact I think a read-eval-print-loop interactive environment would be a great addition to Nice, allowing it to basically displace Python for my uses.

So the big-picture goal for Nice should be: 1) fix java expressive power issues. Easier to program in. Good for "real" programs, not just scripting. 2) eliminate the need for the dual-language solutions like Java + Jython for real programs and scripting. In short: fix java, displace python.

Other languages we should learn from: Scala and Boo are the two in the same category. I'm not sure what's to learn there. Of the scripting-side languages Groovy shares enough syntax that perhaps some of its features can be copied. It appears to have a community and some traction.

-- MikeBeckerle - 22 Dec 2004

 


BlockCallSyntax  

24 Feb 2004 - 19:08 - r1.16   BrynKeller

It would be good to allow a different syntax for method application in some circumstances. Specifically, it would be nice if:

foo
{
 baz();
}

could expand into

foo(()=> 
  { 
     baz();
  });

Basically, if a function call is followed immediately by a block, then the block is converted to a void->A function, where A is the return type of the function, and treated as the last argument to the function call. This part is easy to implement. But what if the block isn't the last argument or there are multiple blocks?

This would allow us to add features like C#'s 'using' keyword, without having to modify the syntax every time we want a new one: Do you have other examples than 'using'?


<A> A using(Disposable resource, void->A func)
{
  try
  {
     return func();
  }
  finally
  {
    resource.dispose();
  }
}

let stream = new FileInputStream("foo");
let value = using(stream) { char c = stream.read(); }

Of course, we might also want something other than a void->A function, perhaps we'd like to have a version of 'using' that doesn't require to first bind the used object to a name. We could solve this by instead expanding the block function into a function which takes exactly the same arguments, with the same names, that the named function takes:

//Assume an abstract interface for disposables here, makes the
//typing nicer.
<Disposable A, B> B using(A resource, A->B func)
{
  try
  {
     return func(resource: resource);
  }
  finally
  {
    resource.dispose();
  }
}

I think it's more consistent to allow argument of function types to be named.

<Disposable A, B> B using(A resource, (resource A)->B func)
{
  try
  {
     return func(resource);
  }
  finally
  {
    resource.dispose();
  }
}

so now we can do

using(new FileInputStream("foo"))
{
  //use the file input stream with the name 'resource':
  char c = resource.read();
}

which the compiler will translate to:

using(new FileInputStream("foo"), (FileInputStream resouce) =>
  {
    //use the file input stream with the name 'resource':
    char c = resource.read();
  });

-- BrynKeller - 31 Oct 2003

The problem with this is that you can't choose the name of the variable so you end up with an general name. And it would get problematic when you nest 'using statements'. I'd rather write something like the following although I have no idea how that would look like on the implementation side of the function.

using(myFile = new FileInputStream("foo"))
{
 //do something with it
}

added some comments in italic -- ArjanB - 08 Nov 2003


I don't know why anyone hasn't recognized it yet, but you are getting closer and closer to the syntax of Ruby. I like the stronly typed-ness of Nice, but Ruby has tons of cool syntax sugar that I would also like to see in Nice. Blocks (or Closures) are only one of them. Many classes in Ruby have been designed to make heavy use of blocks passed to methods. I don't like some of the Ruby syntax, such as the yield call. But still, it would be good for the Nice compiler developers to take a close look at Ruby, and to adopt what they like. It's interesting that Nice has already adopted quite a bit of what Ruby has. They are both interesting languages. I can see, though, that Nice can more easily handle enterprise level projects than Ruby. Here're some links to learn about Ruby:
http://www.ruby-lang.org/en/
http://www.sofer.com/ruby/
http://www.rubycentral.com/

-- TroyHeninger - 12 Nov 2003

Seems more obvious to look at groovy. Maybe Nice has more in common with FlowJava Jiazzi and MultiJava than with scripting languages.

-- IsaacGouy - 31 Dec 2003


Maybe I should look at C# using before commenting but...

How am I supposed to figure out that this

  loop(5) { doSomeThing(); }

is shorthand for this

  loop(5, () => { doSomeThing(); } );

That doesn't look like the same kind of thing; this does

  loop(5, { doSomeThing(); } );

Smalltalk avoids the ugly syntax because blocks (Smalltalk anonymous functions) are objects with defined methods, so we can write something equivalent to { doSomeThing(); }.loop(5) and still have consistent language.

  loop(5) { doSomeThing(); } doesn't seem to fit with the existing forms in the language - it doesn't look like function application; it looks like a keyword but it isn't a keyword.

-- IsaacGouy - 08 Jan 2004

I don't think you should look at it as a shorthand for something else. It's more like a user defined statement.

BTW we are considering making () => doSomeThing(); } equivalent to { doSomeThing(); )

-- ArjanB - 08 Jan 2004

Does user defined statement solve some problem? (Whatever happened to my spirit of adventure!)

Here are some funky apply-to-all expressions

static void Main() {
qs = Queens.queens(7);
qs.{ Queens.printboard(it); };
Console.ReadLine();
}

-- IsaacGouy - 09 Jan 2004

The implicit 'it' variable has problems when you try to nest apply-to-all. apply-to-all looks superfluous for Nice because of the alternatives.

for(it : qs) Queens.printboard(it);
qs.foreach(it => Queens.printboard(it));

-- ArjanB - 09 Jan 2004

Fine with me - I find the qs.{ Queens.printboard(it); }; too cryptic.

-- IsaacGouy - 14 Jan 2004

Notice in the syntax that is currently implemented you have this scoping problem:

    let f = new FileOutputStream("foo");
    using(f)
    { write(f, getBytes("Hello World!"));
    }
    write(f, getBytes("Hey, Please don't let me write to a closed stream"));

The scope of myFile should be inside the using block, not outside the block, so that the second call to write above should fail. This is the same reasoning that allows:

    for (int i = 0; i < x; ++i) { }
as a shortcut for:
    int i;
    for (i = 0; i < x; ++i) { }

For scoping, the example with let above is not particular to the way BlockCallSyntax is implemented, it's the normal rule. We are working on generalizing the for (int i = ...) syntax to arbitrary expressions. This will make the language more coherent, and in particular allow to use it with calls like using, which will allow you to have the scoping that you rightfully want. -- DanielBonniot - 01 Feb 2004

What is the advantage of using(f) { ... } over using(f, { ... });? I agree it is prettier but it looks like a language construct like synchronized instead of a library function. The second form seems more intuitive and is extensible to multiple block parameters:

    <T, U, V | U <: T, V <: T>
    T if2(boolean b, void -> U thenExpr, void -> V elseExpr)
   = b ? thenExpr() : elseExpr();
    
    if2(x < y, { thenDoSomething(); }, { elseDoSomething(); });
BTW, if2 is how the "built in" conditional statements are done in Cecil Language.

-- BrianSmith - 01 Feb 2004

The good thing about BlockCallSyntax is that, although its use will at first seem look like language constructs, it is actually a user-definable form. So after you learn that fact, you see the language as more uniform and coherent. And it will be interesting to see what uses users find for it. For instance, Bryn used it quite cleverly I think in his article about his logging library.

It's true that it does not apply to multiple block parameters, but that could be handled later by extending the syntax. -- DanielBonniot - 01 Feb 2004

Maybe cleaner concurrency (Scala)

      spawn { 
         while(p<n) { p=p+1; buffer put(p); }
      }
-- IsaacGouy - 01 Feb 2004

By amusing coincidence, the same code would look like this with the concurrency library I'm working on for Nice:

  async {
    while(p<n) { p=p+1; buffer.put(p); }
  }

-- BrynKeller - 02 Feb 2004

Now my expectation is that I can generally apply this more uniform and coherent language like this ;-)

   let a = { return 5 + 2; };
   println ( { return 5 + 2; } );

BTW we are considering making () => doSomeThing(); } equivalent to { doSomeThing(); )

-- IsaacGouy - 23 Feb 2004

Yes, you can do that even now. IMO, this is a problem with the type of println. It should not accept functional values. I just sent a message to the nice-info mailing list about this.

Currently, you can write:

    let a = () => "hello";
    // these print "#<procedure gnu.expr.ModuleMethod>"
    println(a);
    println( () => "hello" );
    // these both print "hello"
    println(a());
    println( (() => "hello")() );

With the second kind of block call syntax, you could write:

    let a = { "hello" };
    // these print "#<procedure gnu.expr.ModuleMethod>"
    println(a);
    println( { "hello" } );
    // these both print "hello"
    println(a());
    println( { "hello" }() );

My proposal is that the type system should not allow the calls that print "#<procedure gnu.expr.ModuleMethod."

-- BrianSmith - 24 Feb 2004

I disagree. I see no reason we shouldn't be able to print functional values, even though the message is not (currently?) very informative. What is it about printing methods that bothers you?

-- BrynKeller - 24 Feb 2004

 


BootstrappingFromCVS  

11 Apr 2005 - 12:48 - r1.3   TWikiGuest

Requirements:

Get the Nice module from CVS:

Optionally, if the system nice compiler (which is used for bootstrap) is old:

Compile everything

The resulting nice.jar is in share/java. You can install it system-wide using

(Make sure you have a reasonably up-to-date version of groff - 1.18.1 or later should be OK at least.) (If something still goes wrong, `make fixpoint' may help to recompile some stuff, or `make world', which also runs some tests.)

-- TWikiGuest - 06 Apr 2005

 


ChangeNumberOfTypeParametersInSubclasses  

08 Aug 2003 - 16:13 - r1.2   ArjanB

Does "Modification of the type system for subclasses with a different number of type parameters than the parent." mean that I could do:

class B extends A<Foo> {}
rather than the current approximation:
class B {
  A<Foo> b;
  equals(that@B) = b.equals(that);
  // other wrappers for pass through functions to make B act like an A<Foo>
}

Yet B exists primarily so that functions can require a B rather than allow in any kind of A<Foo>

-- RohanHart - 08 Aug 2003

Yes,

class B extends A<Foo>
would be possible. In such cases the compiler only have to remember that class B has a hidden type parameter Foo. For complex cases and subclasses with more type parameters as the superclass, i don't know if it will be possible maybe can Daniel tell more about that.

-- ArjanB

 


CheckedIntegerArithmetic  

17 Jan 2005 - 20:08 - r1.12   MotiN

The current behaviour of numeric type is to silently overflow. In some cases this is what is needed, and in some cases you don't really care, because it is guaranteed no overflow will occur. However, there are also situations in which you would like a runtime exception to be thrown when overflows/underflows occur (hello, Isaac!).

The JVM does not directly support this arithmetic mode. However, at least for non-long types, it is possible to perform operations on a larger JVM type than the declared type, and then check for overflows. This has of course a small performance hit, but much less than using objects (BigInteger? for instance). So it might be possible to add new types that have overflow detection semantic and good performance. I'll focus on int, but this should be doable for shorter types too. What cases are useful in practice?

Since we want to retain the current semantics for int, we should add a new type, with the meaning "a 32 bit signed integer not modulo 2**32" (that is, which throws an exception when an overflow occurs). I'm not sure what the best name for it would be. integer is a possibility, but I was also considering it for infinite length integers (that is an alias for BigDecimal?). Other ideas: checkedInt (not pretty), checked-int (better, but a new convention for type names), cint (cryptic). Let's use cint in this document, it's short :-) how about checked as a modifier, as in "checked int"?

Regarding typing, int should be a subtype of cint, because you gain "safety" by considering an int as a cint. On the other hand, going from cint to int would later allow overflows to occur, so it should not be automatic. I would also think that cint should be a subtype of long, does that make sense?

Regarding implementation, one possibility is to represent cint as long in the JVM, and to check the result of each operation. Another possibility is to represent cint values as int, but operations on cint values would be performed on long, and the result checked before conversion back to int. The former might be more efficient (less conversions), while the later is more economous in space, which is especially interesting if you have an array of cint. Alternatively, is it possible to detect all/most overflows by working on int only (for instance, for addition, if both numbers are positive, there is overflow if the number is negative)?

-- DanielBonniot - 21 Dec 2003

Overflow detection is possible with int for addition and substraction by sign check. For multiplication, i am not quite shure if even long would be enough. -- TWIkiGuest?

The multiplication of two 32 bit numbers fits on 64 bits without overflow (because log(a*b) = log(a)+log(b)). So it seems we could use int to represent cint, and use temporarily a long for multiplication.

Could somebody actually write the operations as Nice methods (using int as the type)? So a int checkedAddition(int,int) method, ... -- DanielBonniot


I don't think that overflow checking should a part of primitive types because it's not clear when the check should happen(when the result is assigned to a cint or one or both of the operands are cint). Whether to do checking is a property of operators so checked methods or code blocks make more sense.

I have doubts about the usefulness of this proposal and this is VM issue and not a language thing. -- ArjanB - 22 Dec 2003

One way to look at it is that there are three kinds of integer types: modulo integers (higher bits are discarded), limited length (checked) integers and inifite length integers (BigInteger?). Mathematically, the first one makes sense (computing a hash value for instance), and of course the last one too. Checked integers would be useful when modulo is clearly incorrect, but you expect that 32 (or 64) bits will be enough. Using BigInteger? would incur a significant performance penalty, but modulo integers would hide errors if they occur.

So from a language point of view, all three types make sense. Therefore it is not a bug that the JVM does modulo arithmetic, it's useful. If we can use it to provide checked arithmetics too, then all the better.

Rgarding when checks happen, it's simple: they should happen when operations are performed on checked integers. So if you do an operation on two int it will not be checked, if one is int and the other cint, then the type system will decide to call the checked operator, and so there will be a check. With overloading on the result type (which is not available at the moment), we could also say that using the result of a int,int operation as a cint should be a checked operation.

-- DanielBonniot

Many folk seem to forget that JVM does modulo arithmetic - there's a large community for whom this just isn't a problem - whatever I might think. And this isn't something novel that people would be excited about.

Maybe work should concentrate on really ordinary things that will be used a lot (Visibility? Properties?) and really extraordinary things that are made possible by the type system (XML support? Variance sugared syntax?).

-- IsaacGouy - 23 Dec 2003

I agree with these priorities. On the other hand, I believe that the way to accelerate the development of Nice also lies in doing more things in parallel. This means that while the people familiar with the core compiler (Arjan and me) look at features like constructors and properties, it only helps if others are working on tools, libraries, ... In particular, I believe that checked arithmetics is not a hard feature, and that it can be implemented at 90% as user libraries. If somebody provides the checked operations on ints, it should be a matter of say 30 minutes to add the cint type to the compiler. So it won't really slow us down :-) -- DanielBonniot - 24 Dec 2003

With the addition of type declarations(which could allow declaring subtypes of primitives too) CheckedIntegerArithmetic can be a library thing for 100% -- ArjanB

"type declarations" Is there a proposal? -- IsaacGouy - 24 Dec 2003

A cint type seems too low-level since it's tied to JVM details rather than the problem space. I think it would be more useful and more high-level to have checked integer types with a user-specified range. For example, integers in the range [1...100]. That way you find out earlier about incorrect values and the compiler can choose an int, long, or BigInteger? implementation as appropriate. Operations done with these integers would use intermediate values as large as necessary to prevent overflow and do the runtime check when assigning to a non-temporary. (Of course, it's more work for the compiler.) -- BrianSlesinsky - 30 Dec 2003

You may want to check out Javolution and JScience for some nifty ideas. Particularly LargeInteger? (in JScience), and some other stuff in there. I think the idea of using a long for multiplication is good (i.e. result = (long)a * b), then you can do a simple overflow = (result != (int)result). For addition/subtraction, basically, you just have to check that the sign bit (i.e. MSB) is the same as one of the operators. So for result = a + b, overflow = ( (result >> 31 != a >> 31) && (result >> 31 != b >> 31) ) -- MotiN - 17 Jan 2005

 


ClassInvariants  

06 Jun 2003 - 18:48 - r1.4   DanielBonniot

I'm looking ahead to when invariants are added, and the crossover with NiceConstructors. Vague thoughts only, feel free to edit.

There's an Eiffel hack to allow different sets of invariants in different conditions: express your invariants as

invariant_name: condition implies [<an invariant set>]
The trouble with using this for constructors is you have to list what parts of the invariant each method really depends on in each method, which defeats the purpose of an invariant.

I wondered about a distinction between methods that preserve the invariant but don't require it, which could be freely called both within constructors and outside them, and ones that both preserve and require. Note that this is a different situation again to constructors, which do not require the invariant but guarantee to make it satisfied: a preserving-only method would not necessarily make it satisfied if it wasn't when the method was called. The problem with this arises when the preserve-only method is called directly after some buggy method has broken the invariant. The preserve-only method doesn't do the proper checking, because it's happy to accept a broken invariant at method start.

My suggestion is a general condition in_constructor which is set true at the start of each constructor and false at its end. Preserve-only methods guarantee to check the invariant

For this to work with nested constructor calls I guess constructors only set it to false at end if it was false before they set it at start, or something.

Anyway, this is entirely off-the-cuff uninformed thinking out loud, with no idea how implementation-practical the idea is.

-- SamsonDeJ - 15 May 2003

It's a good idea to start with high-level thoughts about the design. If a feature is well designed, it is usually easier to implement it, and of course it makes the language more beautiful.

Could you comment on the proposal in NiceConstructors? If we can separate the construction from the initialization, then there is the possibility to get rid of this invariant problem altogether.

By the way, I appreciate to have somebody fluent in Eiffel to participate in here. It can give a different perspective, and contribute to a richer discussion. Knowing the existing is a must to improve over it.

-- DanielBonniot - 16 May 2003


I would also appreciate hearing from someone who knows Eiffel. Unfortunately it's not me - I know a very little about Eiffel, and picked the above off a webpage. -- SamsonDeJ - 16 May 2003

 


CompilationAPI  

18 Jun 2003 - 14:38 - NEW   DanielBonniot

The compiler can be called from JVM languages (Nice, Java, ...) by using a high level API, instead of starting a different OS process (application). This is used by the command line compiler, but also by IDEs (EclipsePlugin at the moment), and might be useful in other contexts.

The main file defining the CompilationAPI is nice.tools.compiler interface.nice.

One key argument to the compile method is a bossa.modules.Compilation object, which is used to configure the compilation (what package to compile, where to put the generated jar, ...).

The Compilation also contains a bossa.modules.CompilationListener, which receives messages that report the progress of the compilation. Here is its interface:

public interface CompilationListener
{
  void error  (Location location, String message);
  void warning(Location location, String message);

  /** A bug occured in the compiler. 
      @param url the adress where a bug report should be submitted.
   */
  void bug(String stackTrace, String url);

  /** Reports the progress of compilation.
      phase can be: parsing, type-checking, generating code, ...
      the package can be null if the phase applies to the whole program 
      (testing dispatch, creating the archive, compiling to native code, ...).
  */
  void progress(String packageName, String phase);

  /** Gives an approximation of how much of the compilation has been completed.
      @param proportion the current progress 
        (0.0 = just started, 1.0 = complete).
  */
  void progress(float proportion);
}

-- DanielBonniot - 18 Jun 2003

 


CompilerTerminology  

17 Nov 2004 - 19:15 - NEW   ArjanB

Terms that may need explanation related to compilers and typesystems or terms that have specific meaning for Nice.

General

Types

Code generation

Nice specific

-- ArjanB - 17 Nov 2004

 


ConstructorSyntax  

09 Feb 2004 - 00:49 - r1.17   DanielBonniot

I'm trying to summarize my ideas on constructors, based on the discussions we had.

I think we should separate two aspects: creation of new instances, and initialization of new instances. The creation aspect is what interests clients of a class: they want to be able to construct instances that have a certain property, which is described by the arguments they pass. For the author of a class, there are cases where it is possible to return an existing object instead of creating a new one: if the class is immutable, and an object with the correct property already exists. For instance, consider:

class Point
{
  final double x;
  final double y;
}

For a client, a natural way to construct a point would be new Point(x: ..., y: ...);. The author of the class might anticipate or know by analysis that many instances of Point actually have the same coordinates, so he could decide to improve the efficiency by sharing their representation. He should be able to do so without chaning the API, so the clients can still use new Point(x: ..., y: ...);. So he should be able to write a "creation method", for instance:

let Point origin = new Point(x: 0, y: 0);

Point new Point(double x, double y)
{
  if (x == 0 && y == 0)
    return origin;
  else
    return new Point(x: x, y: y);
}

The problem with this is the inside call to new Point(...). It will be a recursive call, and so will never finish (similarly, the value for origin would execute the creation method, which would try to read origin, which is not set yet). One solution would be to treat specially new inside a "creation method". However, this could get messy, and I would prefer a clean solution without such hacks. One idea is to give a special syntax for calling a "real constructor", ignoring creation methods with the same name. For instance:

let Point origin = Point.make(x: 0, y: 0);

Point new Point(double x, double y)
{
  if (x == 0 && y == 0)
    return origin;
  else
    return Point.make(x: x, y: y);
}

With this, we can treat creation methods as normal methods (except for parsing their name). "new Point" is a normal method, so we can define it in a Nicer way:

let Point origin = Point.make(x: 0, y: 0);

Point new Point(double x, double y) = Point.make(x: x, y: y);
new Point(0,0) = origin;

One could be worried that allowing Point.make is exposing a detail about a class: if a client uses it and the class changes so that there is no such "real constructor", then the client will break. However, I think this is fixable. First, the author of the class can provide a CustomConstructor?, which is also reachable with the Point.make syntax. Second, it should be possible to use visibility. Should Point.make be only package visible, not public? This part needs some more thought.

Another good aspect of the make syntax is that it suggest a syntax for CustomConstructors that differentiates them from creation methods:

Point.make(double angle, double distance) = new Point(x: ..., y: ...);

It should even be possible to define Point.make as a normal method:

// Optimization for angle = 0
Point.make(0, distance) = new Point(x: distance, y: 0);

One possible improvement is to allow creation method implementations without a declaration. In that case, the declaration would be taken by looking at matching constructors (custom or not). This would allow the following:

let Point origin = Point.make(x: 0, y: 0);

new Point(0,0) = origin;

This makes some sense because, from the clients point of view, new Point exists even without a creation method declaration, and it defaults to the custructor. Would there be any drawback with this additional feature?

-- DanielBonniot - 18 Dec 2003

It's just struck me that what we're talking about here is very similar to Dylan's way of handling this problem. I'll include a reference here for comparison. Nice is very similar to Dylan in many ways, so it's not a bad idea to see what Dylan does when we have questions about what Nice should do. Instance Creation and Initialization

-- BrynKeller - 18 Dec 2003

A different idea is to use super inside a creation method to refer to the real constructor. This would give the following version for the example:

class Point { double x; double y; }

let Point origin = new Point(x: 0, y: 0);

new Point(0,0) = origin || super;

The syntax new Point(0,0) = origin || super is not intuitive.

Not sure if you are familiar with ||, but this is not specific to constructors. The equivalent code in a more traditional notation would be:

new Point(0,0) {
  if (origin == null)
    return origim;
  else
    return super;
}

I didn't know this because it isn't documented. Now I understand what you meant.

From what I understand you want to allow the user to overload the new operator on a class-by-class basis. I think that is very confusing. When the expression new Point(...) is encountered we expect to have a new object allocated. In particular, it is always the case that

   new Point(0,0) != new Point(0,0)
The idea of object identity becomes unclear because it can't be described in terms of new. Imagine the craziness that would ensue for something like IdentityHashMap<Point,T>.

Yes, you get less control over when a new object is created or not. But that's the idea: most of the time, you don't need to know, and giving you this control causes lots of problems, which is why it is advised to use factory methods. When you call a factory method, you don't know if a new object is created or not either.

Could you give an example of craziness that would ensue with IdentityHashMap<Point,T>?

I will concede that it will not cause problems as long as the documentation is clear that the new operator does not guarentee uniqueness w.r.t. object identity (System.identityHashCode(Object)).

The example above can be written using a factory method, so I don't see what kind of expressivity you are gaining:

    let Point origin = new Point(x: 0, y: 0);
    Point makePoint(double x, double y) = new Point(x: x, y: y);
          makePoint(0.0, 0.0) = origin;

What we gain is that you don't need to defensively write all the code of a factory, just in case it turns out later. Either you do it in all cases, and a large proportion will be wasted effort (even with a good IDE, it's still cluttering the code), or you don't, and then you are stuck since clients started using new YourClass?, and you cannot make the changes that you need without breaking this API. I think these are the same benefits as for properties, where there is a known workaround (getters and setters), but it's a pain to have to do it by hand when the compiler could do it for you.

I disagree. If you start out writing code with the default constructors and then change the fields in the class, you have to remember to add an explicit custom constructor with the old interface to maintain binary compatibility. This is easy to forget to do and the compiler won't be able to help you find this error. For this reason, I think that implicit constructors are bad when used across package boundaries and that explicit constructors should always be used across package boundaries; if VisibilityModifiers were implimented than I would propose that implicit constructors should have package private access. (A more general rule would be that I think that a package's public interface should be explicitly defined in the code.) Once you have written an explicit constructor it doesn't really matter so much which syntax you choose (factory method or constructor), as far as I can tell.
-- BrianSmith - 29 Jan 2004

Also currently we have new Point(...) as equivalent to Point.getClass().getConstructor(...).newInstance(...). But, with the new system, we have don't have this symmetry:

True, but this is a rather lowlevel property, isn't it. How often would it be problematic? How often would the new system safe you work or let you improve your code without breaking the API?

I am just saying that it makes the semantics hard to explain because you can't piggyback on the JLS/JVM specs anymore in these areas. So, you have to write new documentation for the semantics of object creation/identity and for part of the reflection API.
-- BrianSmith - 29 Jan 2004

It would still be possible to offer another construct for surely creating a new instance, provided it's allowed by the class. That can be discussed. Basically, this would make new ... the equivalent of Java factory methods, and the other one the equivalent of Java's new. Since the latter is much rarer in my opinion, we would gain a lot by making it easier.

    abstract class A      { int getValue();
                            // more methods
                          } 
    class Zero extends A  { int getValue() = 0;
                            // specialze other methods for ZERO
                          }
    class Other extends A { final int value; 
                            int getValue() = value;
                            // generic implementations for non-ZERO values
                          }
    let Zero ZERO = new Zero();

Then we could have either:

    new A(int value) = new Other(value: value);
    new A(0) = ZERO;
or:
    A makeA(int value) = new Other(value: value);
      makeA(0)         = ZERO;

I find the second version to be much easier to understand and it can already be done without any language changes. When VisibilityModifiers are implemented then the package author can mark all constructors private and then provide public factory methods like makePoint and makeA. I think this is a good practice anyway.

It's good practice in a language that provides no such feature as we are discussing. The whole point is to make this extra work unecessary.

Isn't the second easier to understand because you are used to it, while the first is a new proposal? Doesn't makeA look like a hack?

More and more Java API's are designed so that the API is (almost) purely defined by interfaces, so that factories must be used anyway. That is the style I prefer so I don't find makeA to look like a hack to me. Anyway, I think the argument could be turned around as "Isn't using constructors easier to understand because you are used to it?"
-- BrianSmith - 29 Jan 2004

Finally, imagine:

    class ColoredPoint { int color; }
    new ColoredPoint(int color) = new ColoredPoint(color:color, x: 0.0, y:0.0);
The coder has specialized Point(0.0,0.0) but this specialization obviously cannot be used by the subclass. So, then you have two sets of rules for deciding what constructor implementation gets chosen (one for direct invocation, one for subclass invocation).

-- BrianSmith - 26 Jan 2004

Yes, this is the distinction between CustomConstructors and OverloadedConstructors?. new Point(0.0, 0.0) is an overloaded constructor, and you cannot use it to construct subclasses, in the same way that in Java, in a constructor you can use a parent constructor but not a parent factory method. Maybe we should say "factory method" instead of OverloadedConstructor??

-- DanielBonniot - 27 Jan 2004

I think that there should be a syntactical distinction between OverloadedConstructors and CustomConstructors. They are different concepts and I think users will get confused by this:
    class Foo { } { ... }

    ....

    new Foo(Number n, Number n) { ... }

    ...

    new Foo(Double d, Double d) { ... }

Is the second constructor above an overloaded constructor, a custom constructor, or a specialization (dispatch-wise) of the first constructor. Maybe you can tell just by reading the code. But, imagine that there are 50 lines of code where the ... lines are. Or, imagine now that all three elements are defined in seperate packages. Now how can you tell?

-- BrianSmith - 29 Jan 2004

Agreed. If I remember, the difference was supposed to come from the presence or absence of a return type (so your first constructor should have one, if it's supposed to be an overloaded constructor, no?). But it's true that if you can specialize an overloaded constructor (which makes sense), then there is syntactic ambiguity.

Any proposal?

-- DanielBonniot - 30 Jan 2004

My proposal is to avoid implementing this feature. :) Or, at least, do not overload the constructor syntax for this purpose. If you do so, then you will have to go to great lengths to document a tedious source-code -> bytecode mapping and/or the binary compatibility rules.

How do you deal with binary compatibility for constructing an instance of a class defined in another package? It seems like inter-package object construction must always go through a "thunk" factory method:

package A, version 1.0:

    class Point
    {
      final double x;
      final double y;
    }

package A, version 2.0:

    class Point
    {
      final double x;
      final double y;
    }
    Point new Point(double x, double y)
    {
        if (x == 0 && y == 0)
            return origin;
        else
            return new Point(x: x, y: y);
    }

package B:

    import A;
    let Point myOrigin = new Point(x:0, y:0);

It seems like you can compile package B as a normal object instantiation (using the JVM's new instruction) against version 1.0 of package A. But, you cannot compile it that way against version 2.0 of package A. I believe that package B should not have to be recompiled due to this change in the implementation of package A, since package A's public interface is the same; that is, I should be able to compile package B against version 1.0 of A and then run package B's code against the compiled version of version 2.0 of A. So, it seems like you have to generate a thunk method equivelent to makePoint for both versions of package A.

I think it would be better to simply discourage people from directly constructing instances of classes from external packages by making all constructors protected by default, and requiring people to add code like:

    // I can implement optimizations like the above in my
    // factory method since the Point constructor is not public.
    public Point makePoint(int x, int y) = new Point(x:x,y:y);
or:
    // I cannot implement optimizations like the above since
    // I am directly exposing a constructor to external packages.
    public new Point(int x, int y);

This makes the language simpler to learn and makes the binary compatibility rules much easier to understand.

-- BrianSmith - 01 Feb 2004

So what you are advocating is exactly the same as Java, right?

It is slightly different. In Java, public classes have an implicit public constructor by default. I am proposing that any implicit constructors be package-private in Nice.

Again, the problem with this approach is that you allow, and even make the "default" since it is easier, to write inflexible code, whose implementation you cannot change afterwards. This is the same problem as methods in C++, which are not virtual unless you explicitely say so, or with fields. So people come up with rules like "always write factory methods" and "always write getters and setters", which indeed avoid the problem, but put the burden on the programmer.

I don't think my suggestion makes it easier to write inflexible code--in fact, I think it does exactly the opposite. Currently, there is no way to enforce that a factory method must be used to construct an instance of your class since the constructors are always public. Therefore, changes to the implementation are restricted because this public constructor must be supported. In my "proposal," the choice of factory method vs. constructor more explicit: if you don't write a public factory method or a public constructor then your class cannot be instantiated from code outside the package at all.

Right, you proposal is an improvement over the current situation in Nice. But it is more inflexible than my proposal because if you don't start with a factory method, you will never able to switch to one without breaking the public API. -- DanielBonniot - 08 Feb 2004

This isn't an issue any more since all object creations will go through factory methods now, right? There remains the issue of whether the factory methods and constructors should be exposed by default but that can be dealt with in VisibilityModifiers.

I don't think using Nice will be more complex with this proposal. It will become easier, because you don't need to worry or bother about factory methods, but if you realize you need to override the default behaviour, you are sure to be able to do it.

It's true that the implementation becomes a bit more complex, but don't worry, I am the one doing it, and I think it's worth the above benefits. About binary compatibility, your solution is correct, and anyway this is an implementation detail (I don't think users should even need to know about binary compatibility rules. Computing power for recompilation is cheap, compilers can be made clever if needed, while user brain's attention is better directed at the design of his program). At the moment, the compiler doesn't check if the public API changed or not, it always recompiles if an imported package changed, which is safe. We might optimize this behaviour in the future, but at the moment I consider more important to "get the language right", so I focus on that. -- DanielBonniot - 01 Feb 2004

You are assuming that package B can be recompiled whenever package A changes, right? But, this is not the case when package A and package B are written by different people, for example when package A is a reusable library packaged in a JAR file and package B is an application that depends on it.

But a new version of A might change its public API. So it is normal for the author of B to recompile his application if he upgrades to a new version of A. It's true that you might be a user of B, you don't have B's source code, and you have a new version of A which does not change its public API but is faster, or safer, for instance. In that case, yes, it's better if you can use the new version of A without recompiling B. But that's a quite peculiar situation. And you should keep in mind that even if A's public interface does not change, it's behaviour/semantics might change, so there is no automatic way the compiler can know if it's safe or not to upgrade A with an old B. But anyway, as you showed, it is possible to keep binary compatibility, it's just a question of implementation, so I would rather that we don't complicate the discussion about the desired definition of the language with this.

I agree, the visibility issue can be discussed in VisibilityModifiers. The other point I was trying to make is that I think that object creation expressions (currently new Point(x:1,y:2), or Point(x:1,y:2) using the syntax you suggested below) should be defined to always invoke factory methods, for the same reasons that motivated the PropertySyntax proposal.

I agree, sorry if that was not clear. -- DanielBonniot


In NiceConstructors, you said "creation = construction + initialization." But, let's extended this to "creation = allocation + construction + initialization" or "new X(...) = allocate X(...) + initialize X()," and by default "allocate X(...) = construct X(...)." Then you could support something like:

    class Point
    {
      final double x;
      final double y;
    }
    // custom factory method
    allocate Point(double x, double y) 
    {
        if (x == 0 && y == 0)
            return origin;
        else
            return construct Point(x: x, y: y);
    }

    // overloaded constructor
    construct Point(double distance, double angle) {
        construct(x: blah, y: blah);
        // instead of "this(x: blah, y: blah);"
    }

    // class instance initializer for Point
    initialize Point {
        ...
    }

Then you would not overloading the new keyword for three different concepts any longer and you avoid ambiguity between overloaded constructors and factory methods.

-- BrianSmith - 02 Feb 2004

Note that you used "overloaded constructor" for what we called custom constructor until now.

Yes, that's a clear distinction of the different aspects, which is important to have in mind. The question is, do we want to use this syntax? It's clear, but it's also very baroque/unusual. What is sure is that we should distinguish the different aspects.

One idea would be to reserve new for constructor declarations, and only the class name for factory method declarations. The idea is that a constructor is involved in the creation of a new instance, while factory methods might return an existing instance, null, ... This would also avoid the ambiguity problem, without introducing those new keywords.

On the usage side, we do not want to distinguish, because the whole idea is that you can evolve the implementation without breaking the API.

We could also support Point(x: 1, y: 2) for calling constructors and factory methods (that is, without the new keyword), since that is a lighter syntax, and puts less stress on the creation of a new instance, which might not be the case anyway. But that's a change that can be done independently of the rest of the proposal.

-- DanielBonniot - 02 Feb 2004

That to make a lot of sense to me; in fact it seems to be the same as my original proposal except that the factory method is automatically generated if an explicit one is not provided. Just to make sure I understand: The expression Point(x: 1, y: 2) would always call a factory method. If a factory method has not been explicitly defined, then there is a compiler-generated one of the form Point(double x, double y) = new Point(x: x, y: y);. What would happen with the expression new Point(x:1, y:2)? Would it be disallowed (allowable only in factory methods from class Point), call a factory method, or directly call a constructor? Personally, I find the idea of new Point(x:1,y:2) expressions not creating a new instance to be confusing.

What would happen if there were multiple constructors defined for the class; would there be an auto-generated factory method for each one?

What would the exact syntax of a factory method be?:

    // same syntax as other methods.
    Point Point(double x, double y) { ... }
or
    // assume the return type is Point.
    Point(double x, double y) { ... }

The Point(x: 1, y: 2) syntax also matches the int('c') syntax already used for primitive types.

    class Point
    {
      final double x;
      final double y;
    }
    // custom factory method
    Point(double x, double y) 
    {
        if (x == 0 && y == 0)
            return origin;
        else
            return new Point(x: x, y: y);
    }

    // overloaded/custom constructor
    new Point(double distance, double angle) {
        this(x: blah, y: blah);
    }

    // class instance initializer for Point.
    // Perhaps the initializer should always
    // appear in the class body so "initialize"
    // doesn't become a keyword?
    initialize Point {
        ...
    }
-- BrianSmith - 02 Feb 2004

The long term goal could be to encourage the use of Point(...) instead of new Point(...) on the client side. But I think for a longish transition period both should be accepted. It would simply be breaking too much assumptions otherwise.

Yes, for each constructor for a given class, there will be a way to create a new instance with those parameters, so that's like an automatically generated factory method. And I think the syntax for factory methods should be just like normal methods. No need for specific treatmeant.

-- DanielBonniot - 03 Feb 2004

OK, I hope that we are getting to a conclusion. CustomConstructors are defined with the new Point(...) { ... } syntax. Later on, we will implement factory methods, defined with Point(...) { ... } syntax. At the call site, one always call a factory method (but that can be the one implicitely defined by a CustomConstructor?. We can also allow the syntax Point(...) for creating a Point, which will address the confusion that Bryn signaled, namely that new Point(...) might not create a new instance.

If there's agreement on this, then I'll release 0.9.6 soon with the current implementation of CustomConstructors, since they seem to fit with the global proposal (that is, source code working with the 0.9.6 release will work the same when the global proposal is implemented).

-- DanielBonniot - 08 Feb 2004

Sure, things make sense as far as I can tell. But, if you are going to recommend that people use Point(...) instead of new Point(...) then I recommend to make that change before you do any more releases. This includes updating the documentation and the examples. Also, are you planning to flag the new Point(...) syntax as deprecated? It seems confusing to have two syntaxes for the same thing, and then also have new Point(...) do three different things depending on the context.

-- BrianSmith - 08 Feb 2004

On the one hand, I agree that the earlier such new syntax is introduced the better. On the other hand, 0.9.6 has already been delayed a lot, because I did not want to release a feature that we were not quite sure was yet in its probable final version. Furthermore, it might be good to have the new creation syntax some time in development version. And it's purpose is especially evident with factory methods, which are not there yet either. We'll see if that can be implemented soon, but I want 0.9.6 released soon (it has several important bug fixes). In any case, we can only start changing documentation after a released version implements a feature.

-- DanielBonniot - 09 Feb 2004

 


CurrentDiscussions  

20 Apr 2004 - 04:22 - r1.12   ChristianS

Discussions of the language aspects of Nice.

 


CustomConstructors  

05 Feb 2004 - 22:38 - r1.27   DanielBonniot

Construction is the process of creating a new object whose fields have some meaningful value. Currently, only the automaticly generated default constructor does that. It takes the value of each field as a named parameter.

Basically, a custom constructor could be defined as a normal method:

class Point { double x; double y; }
Point createPoint(double angle, double distance) = new Point(x: ..., y: ...);

The problem with this solution is that a subclass can not make use of the custom constructor for its parent, since it includes the creation of the object itself, instance of the parent class. Instead, we want the a custom constructors takes the new instance (this), and sets its fields. However, this cannot be done with a normal method, since we do not want to give a way to create an uninitialized instance, as this would be unsafe (like accessing this in a Java constructor is unsafe).

Therefore, we propose to add the concept of a custom constructor. Its declaration is similar to a method default implementation, except that it has no return type, and its name is the class C being constructed, preceded by new. The parameter list is arbitrary, as is the body, except the last instruction: it must be a call of the form new(...), targetting either the automatic constructor, or another custom constructor. This guarantees that all fields are set to a correct value. The body before this last instruction can be used to compute the arguments of this last call. this is not accessible anywhere in the custom constructor, since it is not properly initialized yet.

class Point { double x; double y; }
new Point(double angle, double distance) { this(x: ..., y: ...); }

This allows to create a new point with new Point(angle: ..., distance: ...). Furthermore, a subclass can be constructed by reusing this custom constructor:

class ColoredPoint extends Point { String color; }

var ColoredPoint redOrigin = new ColoredPoint(angle: 0, distance: 0, color: "red");

A custom constructor can also reuse the parent custom constructor indirectly, through the default constructor of the child class:

ColoredPoint(double angle, double distance, int color) { this(angle: angle, distance: distance, color: ...); }

-- DanielBonniot - 01 Oct 2003

Discussion

Calling new C(...) in the constructor seems redundant since C always matches the constructor name, and misleading since we might actually be constructing a subclass. Maybe a syntax like this would work better?

ColoredPoint(double angle, double distance, int color) { new(angle: angle, distance: distance, color: ...); }

Agreed, new C(...) is not a good syntax. We are thinking about using this(...) , but new(...) is an option too.

I updated the syntax above, using this(...). Which one do you prefer: this or new? DanielBonniot

I think this(...) would be too close to Java since the rules are different. (The constructor goes at the end, and this(...) suggests super(...) which doesn't make sense for Nice. But I'll defer to folks who are actually using the language. - BrianSlesinsky

I like being able to do things before calling the parent constructor, with the caveat that "this" is unavailable. But suppose you wanted to keep a hashmap of all objects of a certain type? In Java you'd add "this" to the hashmap in the constructor, which is unsafe but useful. Perhaps there should be a second pass that's started by automatically calling an init() method (if present) after all the constructors have finished?

The generated Java code would be something like:

  this(...);
  if(no subclass or subclass is not written in Nice) { this.init(); }

-- BrianSlesinsky - 13 Dec 2003

This is already possible using initializers, though the subclass check isn't implemented yet.

let Set<Foo> allFoos = new HashSet();

class Foo
{
  {
    allFoos.add(this);
  }  
  
}

-- ArjanB - 13 Dec 2003

Do you want to require that custom constructors should be defined within the class body? I think this is a good requirement because it distinguishes them more from methods. Also, they have access to "this" which should only be available from within the class body. Finally, constructors must be declared in the same package as the class anyway (package b cannot define a constructor for a.A).

There are no such restrictions: CCs can be defined outside classes, and in any package. On the other hand, they don't have access to this, as specified above (accessing this inside a constructor is unsound, since the instance is not yet fully constructed).

Okay, I misread "this is not accessible in the whole custom constructor" to mean "this is not accessible EVERYWHERE in the constructor" instead of "this is not accessible ANYWHERE in the custom constructor."

OK, my mistake, the grammar was imperfect :-) I restore the sentence in its new form, as I assume I got lost by accident.

How do custom constructors relate to SuperCall? It seems they are similar. I wonder if parent constructor invocation can be defined in terms of SuperCall? In Java they use super for both. Is there a reason not to use super in Nice too?

The idea is that every CC must (possibly indirectly) call a default constructor. This ensures that all fields are set. For every parent constructor (custom or default) there is a corresponding default constructor, which calls the parent and set the declared fields of the current class. So this is how you call super constructors. Since you don't call them directly, it would be illogical to use the super keyword.

Thanks, this explanation is what really helped me understand the proposal.

It is not clear from the examples if we are allowed to remove the labels for the constructor parameters, but I assume so since you can't use labels if you are subclassing a Java class anyway:

ColoredPoint(double angle, double distance, int color) { new(angle, distance, color); }

Do the same restrictions apply as in SuperCall? For example, is the following legal?

class A           { A(int f) { myF = f; } 
                    int myF;

                  }
class B extends A { B(int f) { new(myF: f / 2); } // passing different value for f
                                                  // is not allowed in SuperCall

Yes, there is no such restriction for CCs, this is legal.

The parameter list is arbitrary, as is the body, except the last instruction: it must be a call of the form new(...), targetting either the automatic constructor, or another custom constructor. This guarantees that all fields are set to a correct value.

I think this would be more clearly (and correctly) stated as:

The parameter list is arbitrary. If the class has a superclass, then the first instruction of the body must be a call of the form new(...) targetting either another constructor in the class being defined, or a constructor in the superclass of the class being defined. Any code may follow the new(...) call as in a method implementation.

No, we differ from Java here. We can indeed have instructions before the call to the other constructor. Those cannot access this of course, as it would be unsafe. In the current implementation, you cannot write anything after the call, although one could imagine an extension where it would be possible, provided any execution goes through calling another constructor once and only once. Currently, you would use an initializer if you need to do anything at the end.

Furthermore, require that the constructor must assign a value to every field that does not have a default value defined for it in the class's body; i.e. there are no implicit defaults (like in Java where an int defaults to zero if no value is assigned to it). Or, would you like to say that if a constructor parameter has the same name as a field, then that parameter's value is automatically assigned to the field?

This request is not explicitely needed, it's a consequence of the call to another constructor.

State that if a custom constructor is defined then the automatic constructor is not generated (true?).

At the moment the default constructor is still generated. It is still needed, as it is the one that really asssigns the fields. Later, we will introduce a way to make the default constructor private only.

Explain how self-calls dispatch in constructors, if different than dispatch from method bodies.

There is no self-call, since this is not available.

Explain the order in which initialization blocks and constructor bodies are run. Is it even necessary to have initialization blocks anymore?

-- BrianSmith - 18 Jan 2004

Initialization is performed after the execution of constructors. The chaining of constructors is explicit, so there is no special rule. -- DanielBonniot


How useful it is to have code execute before the constructor call? In Java and C++, I have only needed to do this a few times and in all such cases I was able to define simple functions that did the prior computations for me. How much expressivity would be lost if constructor bodies were limited to only a single constructor call, or a series of let expressions and a single constructor call?

Why do you want to restrict what can be done in CustomConstructors before the single constructor call? I see no reason for that and I'm sure someone find useful things you can't do with only let expressions.

It makes the concept simpler and easier to understand. The emperical evidence from Java suggests that making this simplification is not going to cause problems. Assume that custom constructors can only contain a single constructor invocation (no "let"). Then you can write every custom constructor as an equivalence:

    class Point { double x; double y; }
    Point(double angle, double distance)     = Point(x: angleOf(x,y), y: distanceOf(x,y));
or  new Point(double angle, double distance) = this(x: angleOf(x,y), y: distanceOf(x,y));
or  new Point(double angle, double distance) = new Point(x: angleOf(x,y), y: distanceOf(x,y));

You don't have to explain anything like whether or not self is available in constructor "bodies" and whether code is allowed before/after constructor invocations because constructors don't have bodies any more. It makes it clear that a custom constructor is just a an alternative for another (custom) constructor. It also emphasizes that constructors are for initializing a fields values, if you are planning to follow the creation = construction + initialization definition Daniel gave in NiceConstructors. -- BrianSmith - 20 Jan 2004

I often resent this limitation in Java. True you can always work-around it by using help methods, but I think it just clutters the code. Moreover, often you will be able to compute several values at once, but if you don't even have let, you will need to split the computation, once for each argument of the call.

It's true this would simplify the definition, but I'm afraid it is too restrictive. Besides, I expect that the question would pop-up from time to time: "why cannot I do computations before the call?", so we would need to add explanations anyway.

Fair enough. The reason I suggested the possibility of only allowing let was specifically to address the problem you mentioned (computing many values at once) while still having the syntax suggest that the constructor is only for field initialization. But then I realized that even the use of let would almost never be necessary. There is no way to enforce or even suggest (in the language syntax) that any code written in the constructor is relevant to field initialization, if constructs other than constructor calls are allowed in constructor bodies. Therefore, it doesn't seem to make much sense to forbid statements after the constructor call but allow them before. -- BrianSmith - 20 Jan 2004

The "new Point" syntax for defining constructors looks a lot like the syntax used for defining and instantiating anonymous classes (in Java anyway):

    class Point { double x; double y; }
    new Point(double angle, double distance) { ... }   // define Nice constructor
    new Point(a, d) { ...}                             // anon. class instantiation in Java
    new Point(angle:a,distance:d) { ... }              // presumably how anonymous classes
                                                       // would be instantiated in Nice.

When I see the keyword "new" I naturally think an instance is being constructed. Maybe the name of a constructor should just be the name of the class (without "new") like in Java, C#, C++?:

    class Point { double x; double y; }
    Point(double angle, double distance) { this(x: ..., y: ...); } // no "new"

Nice doesn't have anonymous classes but the syntax of CustomConstructors is a topic of discussion. Three choices are not decided definitely at the moment: new(...) or this(...) as constructor call in a CC, requiring "new" or not before the definition of a CC and where CC can be put: only inside class or outside too.

I think this(...) is not a good idea since it seems to imply that self-calls are allowed. Also, I don't like new(...) because I prefer to think of new as the allocate/construct/initialize operator. I think the Point(...) = Point(...) syntax I suggested above is clearest. -- BrianSmith - 20 Jan 2004

Yes, Point(...) has its merits. The only problem I see is that then you could be tempted to write such call with a different class, while that would not make sense. So it has redundant information.

At the moment I prefer this(...). I don't really see it as confusing with self-calls, which are this.foo(...). An advantage is that this(...) really has the same semantics as in Java: "call a constructor from the same class". So it makes sense to use the same syntax.

I agree that if you are going to allow code before/after the constructor call then this(...) makes the most sense out of any points considered to this point. -- BrianSmith - 20 Jan 2004

By the way, I think that this article is a good description of why self-call in constructors causes problems in Java and C#'s way of "fixing" the problem: http://www.jot.fm/issues/issue_2002_11/article4. -- BrianSmith - 19 Jan 2004

Interesting article but C# does only solve one of the problem Java has with constructors. As far as I understand C# doesn't solve the problem as shown in the Parent-Child example at 2/3rd of NiceConstructors page. -- ArjanB - 20 Jan 2004

Agreed, the semantics in C# is not satisfactory either. I think Brian agrees, and was saying exactly that. But the article seems slanted towards C# and does not make this point.

Sure, I know that C#'s solution is not perfectly safe. It disallows self calls in field initialization expressions but allows them in constructors. -- BrianSmith - 20 Jan 2004

What happens when you define a constructor that has a signature matching the default constructor?:

   class Point { double x; double y; }
   new Point(double x, double y)
     { this(x: ..., y: ...); }

Presumably, this would be helpful in order to add exception declarations, preconditions, postconditions, etc. to the default constructor. Yet, it is not clear how the fields of the class would be initialized because a this(...) call would be recursive.

The specification should state that "loops" in constructor calls are not allowed (e.g. a constructor constructor A is defined in terms of constructor B, while constructor B is defined (perhaps indirectly) in terms of constructor A, as in Java. And the Nice compiler needs to check for this, of course. -- BrianSmith - 20 Jan 2004

In case of a CC with the same signature as a default constructor, the current implementation just rejects the call to this(...) as ambiguous.

I agree loops should be detected. Amusingly, the current implementation fails at compile time with a StackOverflowError in such situation. So it seems that the check is there (by chance). OK, the error message could be improved :-)

DanielBonniot - 22 Jan 2004

When I wrote "What happens when..." I meant "what is designed to happen when...." In other words, is replacing the default constructor supposed to be allowed? If so, then how do the fields get initialized (using what syntax)? Using this(...) seems confusing in this situation because you are "calling" the constructor that you are replacing.

I did not really think about it before. A priori it seems to me that this situation could be forbidden. Would that be problematic? -- DanielBonniot

Consider:
    class X { int n; int m }
    new X(int n, int m)              // forbidden because it matches the 
        requires foo(n,m) {          // signature of the default implicit constructor
        this(n:n,m:m);               // confusing: looks (infinitively) recursive
    }       
    new X(Integer n, Integer m)
        requires foo(intValue(n), intValue(m)) {
        this(n:invValue(n), m:invValue(m));
    }
Why should the first constructor be rejected and the second one be accepted? I don't think the first one should be rejected on the grounds that the syntax required to support it is awkward.

It not just that the first one looks recursive, it is ambiguous, using the normal rules of the language. We might create an exception for this case (how would it be phrased precisely?), but before complexifying the language I would like to be convinced this is worth it.

I don't buy the argument about the second version. Integer is a completely different type than int, so there is no ambiguity. (OK, it happens that there is a special conversion in the bytecode, but I don't see how this changes the general point).

-- DanielBonniot - 30 Jan 2004

I put the second one there just to have something similar to compare the first one to. I assume that no matter what you decide the second one would be accepted. -- BrianSmith - 30 Jan 2004

OK. I now think it indeed makes sense to forbid the ambiguous situation. The idea of custom constructors is to offer alternative ways to construct an instance of a class. For instance, even though Points might happen to be implemented by a couple x,y, it is as valid to specify what instance you want with the couple distance,angle, so you can write a custom constructor with that signature. On the other hand, a custom constructor with signature x,y does not make sense, because such way to specify the instance already exists. If you wanted a different behaviour than the default constructor, it would be just confusing (like new Point(x,y) = this(x: y, y: x) !). And custom constructors are not the place to put initialization code, as discussed above, so that's not a reason to want a custom constructor either. -- DanielBonniot - 01 Feb 2004

Then how would one validate the initial values given for the fields of the instance? In the initializer? -- BrianSmith - 02 Feb 2004

When typing is not precise enough, you can specify the acceptable initial values in a requires clause. It would also be possible to use the initializer, but a contract seems more adapted, because it is part of the signature of the constructor (will be printed by NiceDoc, for instance). -- DanielBonniot

But, how would you add a requires clause to the default constructor? That was what motivated my example above. -- BrianSmith - 04 Feb 2004

I see. Since the default constructor corresponds to the internal representation of the class, the requirements could be put in the invariant of the class. -- DanielBonniot

It isn't always possible. Imagine that the precondition for the constructor is "an instance with the given (x,y) coordinates does not already exist in some pool." Then the initializer will add the new instance to the pool. In this case, the invariant for the class would be "an instance with the given (x,y) coordinates does exist in some pool." But, obviously the invariant can't be both at the same time. In other words, the constructor's precondition is only required to hold before construction, but not necessarily every point in time afterwards like the invariant. -- BrianSmith - 04 Feb 2004

Right. For this kind of stateful requirement, you could indeed use an assertion in an initializer. -- DanielBonniot

 


DevelopmentVersion  

06 Apr 2005 - 13:36 - r1.3   TWikiGuest

Before a new version is released, it is sometimes available for testing purposes.

List of changes

You can see the latest list of changes at http://cvs.sourceforge.net/viewcvs.py/nice/Nice/NEWS?rev=HEAD.

Installation

Download http://nice.sourceforge.net/nice.jar, then replace the nice.jar of your current version of Nice with it.

This file is basically CVS updated a few times a day, but only put there if all normal tests are passed, it can bootstrap itself and it can run a few more apps.

-- DanielBonniot - 28 Oct 2002, raboof - 06 Apr 2005

 


DynamicMembers  

17 Nov 2003 - 16:12 - r1.8   DanielBonniot

Dynamic Members

This is the ability for a class to add members to their class at runtime. Actually, that's not what I'm proposing. I really want classes to be able to make it appear that they have other members at runtime. This could be implemented in (at least) two ways.

`.` Operator

One way would be to allow programmers to override the `.` operator. This would be very powerful, especially if the compiler would allow other things besides simple names after the dot, such as ints, floats, or booleans.

Examples

    Object `.`(row@Results, String column) {
        return rs.getObject(column);
    }
    Object `.`(row@Results, int column) {
        return rs.getObject(column);
    }

    Results row = connection.execSql("select fullName, address from Employees");
    String name = (String)row.1;
    String addr = (String)row.address;

If we had unknown implemented (see UnknownType) then this would be even cooler:

    unknown `.`(row@Results, String column) {
        return rs.getObject(column);
    }
    unknown `.`(row@Results, int column) {
        return rs.getObject(column);
    }

    Results row = connection.execSql("select fullName from Employees");
    String name = row.1;        // no type casting needed
    String addr = row.address;

Another advantage to overriding the `.` operator could be to implement dynamic method calls. I haven't explored this idea much, but it could be very powerful.

DynamicMember interface

If allowing an override of the `.` operator proved too difficult (darn), here's another possibility. We could have a special interface, maybe called DynamicMember, or just Dynamic. The compiler could assume that any class that implemented this interface would have a Object getMember(String name) method, or something similar. It would call this instead of it's normal field lookups.

Normal Members

The compiler needs to be intelligent enough, however, to do normal member lookups for the normal (public, protected, and private) members of the class. It would only do dynamic lookups when members are accessed which have not been declared. This means that dynamic members may not be found at runtime. Which necessitates a possibly new Exception class for this situation, which the programmer of the dynamic class would throw.

Reflection

It would be a really cool bonus, I think, if Nice could implement reflection on these dynamic members, so they would appear as if they were full-class citizens with the normal members of the class.

-- TroyHeninger - 25 Oct 2003

One question is whether this is important to use . in these cases. Sure, it looks good. On the other hand, it can hide the fact that the operation can fail. In that case, you could decide to use another operator, say `/`:

    <T> T `/`(row@Results, int column) = cast(row.getObject(column));
    <T> T `/`(row@Results, String column) = cast(row.getObject(column));
then you can use it with row/1 or row/"address".

The nice part about this solution is that the compiler does not need to be modified. With `.`, it should mostly be a parsing issue, but it could reveal somewhat tricky still.

Note that for SQL, one could do something even nicer using tuples:

  <T1,T2> (T1,T2) execSql2(Connection c, String query) ...
...
  (String name, String adresse) = connection.execSql2("select fullName from Employees");

With this, you don't even need to handle the result object. Wait, that requires that the fields are ordered, is it the case? Otherwise, you would need to pass the names of the fields you want inside the result (but then you don't need the 2).

-- DanielBonniot - 25 Oct 2003

I think it's not a good idea to overload `.` and `/` doesn't look pretty. Why not use the [] syntax in this case?

    <T> T get(row@Results, int column) = cast(row.getObject(column));
    <T> T get(row@Results, String column) = cast(row.getObject(column));

Note that these casts are only needed because these java methods aren't retyped yet.

You can use these 'get' methods like:

String name = row[1];
String addr = row["address"];

-- ArjanB - 25 Oct 2003


I agree that overloading the `[]` operator is a workable solution. But I'd still like everyone to explore the concept of adding runtime members and methods. I'd like you to think again about the proposal for a class to override an interface to accomplish this, called DynamicMembers or DynamicMethods. These could be defined as follows:
interface DynamicMembers {
   java.lang.reflect.Field reflect(String member) throws NoSuchFieldException;
   <T> T get(String member) throws NoSuchFieldException;
   <T> void set(String member, T value) throws NoSuchFieldException;
}

interface DynamicMethods {
   java.lang.reflect.Method reflect(String method) throws NoSuchMethodException;
   <T> T call(String method, Object[] args) throws NoSuchMethodException;
}
The Nice compiler would compile code that accesses any undeclared methods or members without a compile error, but only when a class implements these interfaces, respectively. It would produce bytecodes that call the methods of these interfaces. Classes implementing these would be able to easily, dynamically add members or methods at runtime by implementing these interfaces.

Lastly, if no one has time to look into implementing these in the compiler, I'd be happy to take a stab at it myself. But I'd need to be added as a developer to the project. And I'd like to be given at least some pointers to where I should start looking at the necessary changes.

-- TroyHeninger - 11 Nov 2003

Could you give an example of application of these Dynamic interfaces? Above, you first introduced them as an alternative to overloading `.`, in case that is too complicated. But overloading `.` is rather simple, it's just a matter of parsing. The only question about it is wether we really use the `.` symbol (elegant, but possibly confusing) or use another symbol. The Dynamic interfaces look harder to implement, but they are also more powerful, since they are a runtime feature, while `.` is compile time. So examples would help, with comparison with, for instance, Arjan's proposal.

We will certinaly be glad to welcome you in the development team. The tradition is to first let you submit a few patches, and then grant you commit rights. That should not restrict you in the begining.

-- DanielBonniot - 12 Nov 2003

Worthy Examples

I can think of three examples off the top of my head: web programming, database programmin, XML programming, and properties. I'm sure there are many more. Let me illustrate each of these, though I don't have time at the moment to be thurough. I'll add more later...

Web Programming

When your page or servlet receives an HTTP request, instead of getting a simple javax.servlet.Request object, you would get a DynamicMember. All variables passed thru the URL (using GET) or thru a form (POST) would be available as runtime members of thi object. Also, the session object would be a DynamicMember, so that it's members were set at runtime throughout the life of the session. In a language I designed a few years ago, I also had properties attached to web folders/applications, and the servlet's init parameters that both used the DynamicMembers concept. I also had a temp object for each page that was dynamic, that wouldn't get passed in calls to other pages.

Database Programming

Each ResultSet? object should also be a DynamicMember so that each column can easily be accessed or changed as if it's part of the language. I referred to this idea in the introduction above.

XML Programming

XML would be a natural for this. Each Node would be a DynamicMember so that child nodes could be easily accessed, added, changed, or removed at runtime.

I'll add example code, if you need, when I have a little more time. But I hope I've opened your eyes to the possibilities.

-- TroyHeninger - 13 Nov 2003

For XML, you could use the DTD/schema to automatically generate a staticly typed view of the document (this is something very interesting to me, I would love somebody to explore this idea).

Could you, for instance, expand the database example, and explain how your proposal would improve over Arjan's?

-- DanielBonniot - 17 Nov 2003

 


EclipsePlugin  

10 Jan 2005 - 06:47 - r1.35   TWikiGuest

On this page the Nice Eclipse Plug-in is described

What is it?

The "Nice Eclipse Plugin" is a plugin for the open source Eclipse IDE. It is possible to extend the platforms functionality by new third-party plugins. This plugin enables developers to manage and compile nice project in Eclipse. Every Eclipse plugin has a unique ID, the ID of the Nice plugin is "net.sf.nice".

The funny thing is that the plugin itself is written completely in Nice.

enjoy!

The Plug-in's progress

Download

The plugin sources are accessible by CVS in the module "eclipse".
A distributable zipped archive version is available here.

Build

Use jakarta Ant to build the plugin. In the file nice_plugin_build.properties you have to adjust the following properties:

The following targets are available:

Installation

If you downloaded the zipped plugin then all you have to do is to extract the zip archive and move the plugin folder in the eclipsehome/plugins folder.

If you got the CVS version, then type:

ant install
This will build the plugin sources and and install the plugin folder in the eclipsehome/plugins folder. Older versions will be removed.

Usage

now compilation should be started
a file nice1.jar is created in the "eclipse/workspace/nice1" folder

the error is reported to the console for debugging reasons
a "Problems" view should be opened with the error/errors

if the view is still empty then click on the black triangle on the right of the problems view title bar

select "Filters..."
check "Nice Problem"

Troubleshooting

If you experience an unexpected behaviour sheck the following by Menu Help > About Eclipse Platform >

or look at the logfiles

Documentation

You can find a fast intro on the exclipse workbench at Worbench Userguide (pdf)

Plugin development guide: Plug-in Developer Guide (pdf)

Eclipse Naming Conventions

User feedback

Question:
How will this work in a multi-language project (say, Nice and Java, like in the Nice compiler source)? The source files will be opened in different editors, depending on the extension? -- DanielBonniot - 10 Jun 2003

Answer:
Yes, in the Nice-Project, that can contain diffferent file types, always the appropriate editor is opened. -- AlexGreif - 12 Jun 2003

Question:
What is Nice-Project? --Daniel

Answer:
with Nice Project I mean a special eclipse project Type, that was created by menu File > new... > Project... > Nice =. A Nice-Project knows which filetypes how to handle and how to invoke the compiler. In eclipse the terminus =Nature makes it possible that projects behave differently -- AlexGreif - 15 Jun 2003

Question:
If I write an ant build file for that project, will it be possible that compile errors are parsed correctly, depending on whether they come from javac and nicec?

Answer:
all errors should land in the task view, independently from which compiler. This is the desired solution. Isn't it? -- AlexGreif - 12 Jun 2003

Yes. But if the compiler was invoked by ant, I wonder how the information can be passed to eclipse through ant. --Daniel

If you build the project by ant, in a java-Project, all ant compilation errrors are "routed" in the Task view. If a java-project can to this, then we should be able to do this too :) -- AlexGreif - 12 Jun 2003

Question:
Does eclipse support Makefile too?

Answer:
I dont know, we have to look :) -- AlexGreif - 12 Jun 2003

I know, these are advanced features. I'm just curious. For the moment, support for Nice-only projects would already be great. Keep up the good work! -- DanielBonniot - 10 Jun 2003


This plugin is a good reason for me to try out eclipse. -- ArjanB

Development

Interfacing with the compiler

See CompilationAPI.

AST

Looks useful to me. By the way, does the compiler offer a convenient way of obtaining the AST? Do we have a pretty-printer that will generate Nice source code from the AST? These could be important for this plugin (or others), if we want to support automated refactoring operations.

-- BrynKeller - 11 Jun 2003

No, the compiler offer no easy way to obtain the AST. And pretty-printing is only very limited because it's only used for creating *.nicei files. Both things could easily be implemented once the bossa.syntax package is completely converted to Nice. -- ArjanB

At the moment, the compilation API only allows a full compilation. It would not be very difficult to add an API to get an AST. It just needs to be defined: should we pass a package name and get back a list of AST for all files in this package and the imported packages? Or work on a file-by-file basis?

Pretty printing would need to be written (at the moment there is a toString method, but it won't create indentation, for instance). I'd suggest writing a Nice multi-method for pretty-printing, so it could be kept in a separate package. The root class for an AST is bossa.syntax.AST.

-- DanielBonniot

Syntax Highlighting

If you need it, I want to help the syntax highlighting since I familiar with the grammar of Nice and I have some time. -- ArjanB

We have to collect ideas how to realize syntax highlighting. My suggestion is

All editors that I know use the second way, they scan the source for strings and apply the rules in for of setting style and color.

Would it be possible to use the default colours used by the Java Editor (until we implement a Window / Preferences / Nice / Syntax notecard for selecting colours -- IsaacGouy - 19 Feb 2004

I think the first suggestion is better, because we let the nice parser determine which words are highlighted. On the other hand we have to measure how performant on the fly parsing is.

Maybe there is a way in eclipse to parse only the relevant parts of the edited document, and not the whole file all the time. -- AlexGreif - 12 Jun 2003

The parser is not very adapted for syntax highlighting because:

It seems that we need three parsers, for the compiler (can be used for refactoring too), NiceDoc, and syntax highlighting. They are similar, but have different requirement. Does anybody know a way to share the common parts, while getting the different behaviours? -- DanielBonniot - 12 Jun 2003

yes that would be a good thing! -- AlexGreif - 12 Jun 2003

-- AlexGreif - 12 Jun 2003

I think implementing simple keyword highligthing is a good start. -- DanielBonniot - 12 Jun 2003

OKwe will take this for the first proto , then I can use the Ruby example :)) They do it the simple way too -- AlexGreif - 12 Jun 2003

We don't need three parsers because the NiceDoc comments could be parsed by the compiler and be put in the AST. This allow better linking between NiceDoc pages because the compiler can know wich method implementation belongs to which method definition and vice versa.

The parser for the plugin could be a lot simpler than the one for the compiler so sharing common parts might be not worth the effort.

-- ArjanB

I would prefer the parser in the final solution.

The question is, how should the parser return the syntax information?

It depends how eclipse allows us to implement it, but IMO the third one is the best.

-- AlexGreif - 12 Jun 2003

For syntax highlighting, it seems to me the best would be to implement an generic SyntaxHighlighter?. It would take as input a java.io.Writer, and return as output a list of specifications: at such position there is a keyword, at such other position there is the name of a variable being defined, ... Would it be easy to do the highlighting in the text editor, given this info? -- DanielBonniot

That ist my third suggestion. Isnt'it? -- AlexGreif - 12 Jun 2003

It should probably be started in a low-priority thread, so it does not slow-down the system when writing. -- DanielBonniot

I have to examine how to start threads in eclipse. I think eclipse hast its own way to handle threads. -- AlexGreif - 12 Jun 2003

A good thing is that SyntaxHighlighter? could be shared among several editors (think JEdit).

If we think, in the long term, about refactoring, showing the definition of a class and automatic completion, which basically mean parsing the whole program, this could be seen as duplicating effort. On the other hand, it could be nice to have syntax highlighting on syntactically incorrect programs (when you are writing a method, and it is not finished yet), and then SyntaxHighlighter? needs to be quite different from a normal parser anyway. -- DanielBonniot

Maybe thats the way they have siple word matcher for syntax Highlighting -- AlexGreif - 12 Jun 2003

Do we know how code completion works in eclipse plugins? -- DanielBonniot

not yet :)) -- AlexGreif - 12 Jun 2003

Compiler Invocation

In the first run I will embed the nice.jar in the temporary (net.sf.nice.compile) plugin. This makes it fast to implement the plugin proto. If we get more experience how to handle only one nice.jar on the whole system, we will get rid of this temp plugin. -- AlexGreif - 12 Jun 2003

Question:
Should there be a way to specify compilation options (the main package, class directory, classpath...). -- DanielBonniot

Answer:
we should specify the most necessary things in the main preferences (Menu Window > Preferences > Nice). And project specific preferences can be set in the project itself. -- AlexGreif

Question:
Or should we require that the user writes an Ant build file to do that? (Is there a good assistant to write build files? Or maybe the nice plugin could contain an editor to create sections in a ant build file specifically for the nicec target, listing the available options?). -- DanielBonniot - 12 Jun 2003

Answer:
Only ant script is not enough. Its not very user friendly. There is another plugin that lets one build ant scripts. we can make our plugin dependant on the ant-plugin. -- AlexGreif

I managed to compile a Nice project, by writing a ant build file! The editing was in a text window, but there was automatic tag completion. Is this what you were refering to, or is there something more user-friendly? -- DanielBonniot

Its another ant plugin. I deleted it two days before so I cannot tell whats it exacly doing. But it helps with editing the ant script maybe in a graphical way -- AlexGreif - 12 Jun 2003

 


EnhancedNullTesting  

11 Apr 2005 - 14:50 - NEW   TWikiGuest

http://sourceforge.net/tracker/index.php?func=detail&aid=671444&group_id=12788&atid=362788

Section "Non-local variables" in http://nice.sourceforge.net/cgi-bin/twiki/view/Doc/OptionTypes

http://confer09.condor-edv.com/nice@freenode/2005-04-04.html chatlog

-- Main.Raboof - 11 Apr 2005

 


EnumImplementation  

16 Jan 2005 - 15:22 - r1.8   MotiN

Nice will get enums soon but first the exact implementation and syntax needs to be discussed.

Specification

A good starting point is the java 1.5 enum proposal: http://www.jcp.org/aboutJava/communityprocess/jsr/tiger/enum.html

An example of the java proposal:

public enum Coin {
  penny(1), nickel(5), dime(10), quarter(25);
 
  Coin(int value) { this.value = value; }

  private final int value;
  public int value() { return value; }
}
In Nice we could make the syntax simpler:
public enum Coin(int value) { penny(1), nickel(5),  dime(10),  quarter(25)}

Implementation

And the compiler would generate in case of this example something like:

abstract class Coin implement Enum {
final Coin penny = new penny();
final Coin nickel = new nickel();
final Coin dime = new dime();
final Coin quarter = new quarter();
}
final class penny extends Coin{}
final class nickel extends Coin{}
final class dime extends Coin{}
final class quarter extends Coin{}

int value(Coin);
value(f@penny) = 1;
value(f@nickel) = 5;
value(f@dime) = 10;
value(f@quarter) = 25;

-- ArjanB - 30 Apr 2003

An alternative is not to declare a class for each value, but make them an instance of the same class. An advantage is that we generate less classes, which should improve runtime efficiency (loading classes takes time to the jvm). If we did that, then we cannot use class dispatch for methods. We could either compare references, or assign a unique small number to each case, and use a switch bytecode to dispatch. This is an implementation detail, and should not make any difference in the specification part. This makes it possible to use the class implementation first since it seems simpler, and to optimize for speed after the implementation works well.

-- DanielBonniot - 30 Apr 2003

We can use dispatch on value for enum by giving each element a final field(named ordinal?). It is only a bit more work.

Another implementation problem is how do we prevent the addition of elements after the enum is made. It should not be possible because it might bypass the coverage tests.

-- ArjanB

An important question is: should enums be extendible? It's tricky because then a inverted inheritance tree for enums is needed. I think it's doable although I haven't figured out the details yet.

Because of the complexity for the users and of the implementation, Java 1.5 will not have extendible enums.

-- ArjanB - 16 May 2003


Even though I am not a fan of enumerations, I had this idea when I was walking home yesterday for a safe switch construct for enumerations. Consider, that for every enumeration, two methods switch and switch_default are automatically generated in the same package like this:

  <Any T> switch(Coin c, void->T penny, void->T nickel, void->T dime, void->T quarter) {
        if      (c == Coin.penny)   return penny();
        else if (c == Coin.nickel)  return nickel();
        else if (c == Coin.dime)    return dime();
        else if (c == Coin.quarter) return quarter();
        else throw new Error("something is seriously wrong");
  }
        
  <Any T> switch_default(Coin c, void->T default,
                                 void->T penny   = default,
                                 void->T nickel  = default,
                                 void->T dime    = default,
                                 void->T quarter = default)
        = switch(c, penny, nickel, dime, quarter);

Also, assume that there is a different anonymous function syntax as Arjan hinted at in BlockCallSyntax, where "() => doSomeThing(); } is equivalent to { doSomeThing(); )". Then, we can write:

let size = switch(c, penny:   { return 2; },
                     nickel:  { return 3; }, 
                     dime:    { return 1; },
                     quarter: { return 4; });

Note that this would be "safe," because if you add another enumeration value (e.g. half_dollar) then the signatures of the switch and default_switch methods change, and all callers of those methods will have to be updated in order to compile properly (like when adding a constructor to an algebraic datatype in ML). Presumably, during code generation these calls could be translated into the same JVM instructions that Java switch statements use.

Anyway, I still am not sure that enumerations are useful, and it seems like this does not have any value over the method dispatch technique below, but I wanted to present this idea before I forgot it:

    int coinSize(Coin c);
    coinSize(penny) = 2;
    coinSize(nickel) = 3;
    coinSize(dime) = 1;
    coinSize(quarter) = 4;

    let size = coinSize(s);

-- BrianSmith - 21 Feb 2004


I saw an implementation like the following a while ago, which I think does it quite nicely. Consider it as a pattern to be generate when ever an enum is specified:

final public class Coin {

    public final static Coin PENNY   = new Coin("Penny");
    public final static Coin NICKEL  = new Coin("Nickel");
    public final static Coin DIME    = new Coin("Dime");
    public final static Coin QUARTER = new Coin("Quarter");

    final String name;

    private Coin(String name) {
        this.name = name;
    }

    public String toString() {
        return name;
    }
}

An example of usage:
Coin aPenny = Coin.PENNY; // ok
Coin aHalfDollar = new Coin("HalfDollar"); // fails due to private constructor

This has some advantages in that one can't add on to a declared enum, code is readable, equals(), hashCode(), and == operator (i.e. identity) work nicely, as does toString(). Of course, it's type-safe too. On the downside, it depends on access modifiers, which don't exist yet in Nice (but will be implemented, of course).

If one wants to associate values with the enum, then this implementation is no good, of course. Though one could probably handle that by changing from what one generates the resulting code to be like in the Java 1.5 spec and then generate the following:

final public class Coin {

    public final static Coin PENNY   = new Coin("Penny", 1);
    public final static Coin NICKEL  = new Coin("Nickel", 5);
    public final static Coin DIME    = new Coin("Dime", 10);
    public final static Coin QUARTER = new Coin("Quarter", 25);

    private final String name;
    private final int value;

    private Coin(String name, int value) {
        this.name = "Coin." + name; // replace "Coin." with fully qualified class name perhaps. or eliminate (?)
        this.value = value;
    }

    public String toString() {
        return name;
    }

    public int value() {
        return value;
    }
}

-- MotiN - 16 Jan 2005

 


FeatureProposals  

23 Jun 2005 - 00:08 - r1.19   TWikiGuest

This page is where you can propose new features for Nice. page. You can also edit a feature page to comment on the proposal.

Implemented features:

How is this section different from CurrentDiscussions?-- IsaacGouy - 31 Dec 2003

 


FieldTypeOverriding  

02 Aug 2003 - 08:24 - r1.2   DanielBonniot

It is often useful to declare that, in a subclass, a certain field of the superclass has a more precise type. To be safe, this feature only applies to final fields.

class A
{
  final Reader reader;
}

class B extends A
{
  override FileReader reader;
}

The new type must be a subtype of the original type, and the original field must be final.

Implementation notes: the type in the default constructors of B must be changed. For the field access methods, the get method can simply be overriden.

-- DanielBonniot - 21 Jul 2003

This is implemented in the DevelopmentVersion (future 0.9.1) of the compiler.

-- DanielBonniot - 02 Aug 2003

 


FlagInterfaces  

06 Jun 2003 - 19:17 - r1.7   DanielBonniot

This page shows the concept of FlagInterfaces to solve the typesafety problem of the collections api. Note: this is an immature proposal and the syntax will change problably.

A flag interface is an interface with some restrictions it can not have methods and is not an independant type. It can only be used to refine the type of a normal interface or class.


Here a selection of the declarations in the collections api enhanced with FlagInterfaces:
flag CollectionAcces Immutable;
flag Replacable extends Immutable;
flag Reducable extends Immutable;
flag Appendable extends Immutable;
flag Mutable extends Replacable, Reducable, Appendable;

interface Collection@Mutable<E> has CollectionAcces{}
interface List@Mutable<E> extends Collection<E> {}
interface Iterator@Mutable<E> has CollectionAcces {}
interface ListIterator@Mutable<E> extend Iterator<E> {}

<E> boolean contains(Collection@Immutable<E>, E);
<E> int size(Collection@Immutable<E>);
<E> boolean remove(Collection@Reducable<E>, E);
<E> boolean add(Collection@Appendable<E>, E);
<E, CollectionAcces T> Iterator@T<E> iterator(Collection@T<E>);

<E> E get(List@Immutable<E>, int);
<E> E set(List@Replacable<E>, int, E);
<E> E removeAt(List@Reducable<E>, int);
<E> void add(List@Appendable<E>, int, E);
<E, CollectionAcces T> ListIterator@T<E> listIterator(List@T<E>);

class Vector@Mutable<E> implements List<E>{}
class Array@Replacable<E> implements List<E>{}

public void main(String[] args) {
List<String> mylist = new Vector(); //convenience we take the default CollectionAccess type of List here
// List@Mutable<String> mylist = new Vector(); //so this line is the same
mylist.add("abc");
Collection@Immutable<String> coll = mylist; //coll is a immutable view of mylist
coll.remove("abc");//error not allowed
Collection@Appendable<String> c = coll;// error not allowed
}

The same code after removing the syntatic sugar:

interface Immutable{}
interface Replacable extends Immutable{}
interface Reducable extends Immutable{}
interface Appendable extends Immutable{}
interface Mutable extends Replacable, Reducable, Appendable{}

interface Collection<E, +T | Mutable <: T>{}
interface List<E, +T | Mutable <: T> extends Collection<E,T> {}
interface Iterator<E, +T | Mutable <: T>{}
interface ListIterator<E, +T | Mutable <: T> extend Iterator<E,T> {}

<E> boolean contains(Collection<E,Immutable>, E);
<E> int size(Collection<E,Immutable>);
<E> boolean remove(Collection<E,Reducable>, E);
<E> boolean add(Collection<E,Appendable>, E);
<E, T> Iterator<E,T> iterator(Collection<E,T>);

<E> E get(List<E,Immutable>, int);
<E> E set(List<E,Replacable>, int, E);
<E> E removeAt(List<E,Reducable>, int);
<E> void add(List<E,Appendable>, int, E);
<E, T> ListIterator<E,T> listIterator(List<E,T>);

class Vector<E, +T | Mutable <: T> implements List<E,T>{}
class Array<E, +T | Replacable <: T> implements List<E,T>{}

public void main(String[] args) {
List<String,Mutable> mylist = new Vector();
mylist.add("abc");
Collection<String,Immutable> coll = mylist; //coll is a immutable view of mylist
coll.remove("abc");//error not allowed
Collection<String,Appendable> c = coll;// error not allowed
}

An experiment as proof of concept of the way of typing, the commented lines are type errors: package test;
interface I{}
interface J extends I{}
interface K extends J{}

class X<+T | K <: T>{}
class Y<+T | J <: T> extends X<T>{}
void foo(X<I>) = println("foo");
void bar(X<J>) = println("bar");

public void main(String[] args) {
X<K> x = new X();
X<J> y = x;
X<I> z = x;
Y<J> a = new Y();
Y<I> b = a;
//Y<K> c = a;
X<I> d = a;
X<J> e = a;
//X<K> f = a;
a.foo();
a.bar();
b.foo();
//b.bar();
d.foo();
//d.bar();
e.foo();
e.bar();
}

-- ArjanB - 26 Apr 2003


The problem with lazylists can be solved by an additional FlagInterfaces.
interface Sizeless {}
interface Immutable extends Sizeless{}                                        
interface Replacable extends Immutable{}
.... // rest of the interfaces

<E> boolean isEmpty(List<E,Sizeless>); //isEmpty is possible on lazylist
<E> int size(List<E,Immutable>);  // but size is not

class LazyVector<E, T+ | Sizeless <: T> implements List<E,T>{}

An advantage of using type parameters to restrict methods is that only a few interface need to added. I think this can be used without changing the existing collections api. Only retypings will be needed.

An important part of this proposal is the default type parameter of each collection interfaces and classes. This improves the ease of use. Only when writing new methods or using a more restrictive view of the collection class, is additional typing needed.

Daniel does the way of typing make sense?

-- ArjanB

Interesting. I would have to think more in details. It seems like it could work. Have you seen my comments on the JINX page? yes

There I mention & types, and how they can be syntaxtic sugar for constrained types. It would be interesting to compare the two.

One issue is whether we need to be able to dispatch on "flags", or is this just to give types to existing methods. I think if we don't modify (wrap) the collection API, we cannot dispatch on, say, Immutable. Or maybe it would be the same as the list of classes that implement it? I think so

We cannot dispatch on type parameters. With & types, when you declare your own hierarchy, you could really create the interfaces, so you could dispatch.

I think with both proposals, we would have a similar API.

-- DanielBonniot

I think you should view "flags" as a kind of abstract interface so you shouldn't need to dispatch on them.

Both proposals should be worked out so we can make a good comparison. -- ArjanB

 


FunctionsReplacedByMultiMethods  

18 Oct 2003 - 15:06 - r1.2   DanielBonniot

Note: this has been implemented, as of Nice 0.9.2 -- DanielBonniot - 18 Oct 2003

Imported email discussion: Could there be a way to also be able to separate the declaration and the definition of a function ? I was thinking about this, since if we could do so, we could really divide declarations and implementations. Thus being able to write files that only contain the 'API' of a package, but not showing the implementation. -- GamsL - 19 Sep 2002

The naive way would make it look like a multi-method. So how would we distinguish them?

One possibility would be to get rid of functions, and only keep multimethods.

Advantages

Simplification. There is only one concept instead of two. People don't need to learn two different syntaxes, and to understand the differences. Better extensibility. A problem with using functions is that you might think when you declare it that you won't need to have several implementations, but then you find out later that you were wrong. If it had been a multi-method from the start, there is no problem here. Exactly this poses a problem ! You remember I had to let the functions work with multimethods (in their body) to guarantee exhaustiveness !

Separation of declarations and implementations. This would be very nice !

Drawbacks

Currently calling a function is more efficient than calling a method, even if there is only one implementation. This could be overcome by an optimization in the compiler. We would loose the ability to forbid new implementations (like final methods in Java). Often this is used to optimize dispatch speed. Since the dispatch code is written at link time in Nice, the compiler can optimize it automatically. Are there justifications for "closing" a method? It is a philosophical question. Some would say that it allows to reason about the exact behaviour of the method. Others would say that "closing" is against the idea of Object Orientation, where everything is open for specialization. Maybe the addition of design by contract can help, since it will allow to impose restrictions on the reimplementations of the method. Will people miss functions? For instance, it seems that the Dylan language used to have only methods, and that they added functions later. So should we go the other way around? See http://www.gwydiondylan.org/old-docs/htdocs/proposal-define-function.txt and http://www.functionalobjects.com/products/doc/core/core_8.htm. I think so too ! What if a programmer uses a final method to optimize dispatch speed ? There might be cases where this feature is solely used for this purpose, and it would be perfectly alright (or even desirable) to add a new implementation ! I guess this should not be forbidden, since DesignByContract? could maybe handle most of the cases where restrictions are necessary, anyway ?!

Proposal

Remove the concept of toplevel function Still accept the current syntax for functions. It will mean: declaration of a multi-method, and default implementation. I like this idea, it fits well I guess !

This has the advantage of keeping backward compatibility with programs using functions. You can still declare a method without the implementation(for instance to separate it in a different section or file). We still keep the distinction between method declaration and method implementation, which I think is very important (while it is blured in Java).

Will it then still be possible to provide the default implementation somewhere else, and just define a method ? Or will it then be necessary to define the default implementation like one currently defines a function ? I shouldn't think so !

Advice

Currently you should keep on using functions when appropriate.

They are more efficient at the moment If I do the change, the same syntax will remain valid, so you won't have anything to change in your source using functions It is less work :-) -- DanielBonniot - 19 Sep 2002

 


HandlingJNI  

20 Apr 2004 - 04:38 - NEW   ChristianS

First some simple examples how JNI in JAVA works:

Test.java:

class Test 
{
  static {
    System.loadLibrary("test");
  }
  
  public static void main(String[] args) 
  {
    System.out.println(runTest());
  }
  
  private static native String runTest();
}

Ok, first compile the JAVA class:

javac Test.java --> Test.class

Now generate Header:

javah Test --> Test.h

This results in the following Test.h:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class Test */

#ifndef _Included_Test
#define _Included_Test
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     Test
 * Method:    runTest
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_Test_runTest
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif

Ok, lets write a implementation Test.c:

#include <stdio.h>
#include "Test.h"

JNIEXPORT jstring JNICALL Java_Test_runTest (JNIEnv *env, jclass c) 
{
  jstring value;
  value = (*env)->NewStringUTF(env, "TEST-jni");
  return value;
}

Ok, this is a real basic implementation. But let us compile the library:

gcc -I/site.opt/Java/j2sdk1.4.2/include -I/site.opt/Java/j2sdk1.4.2/include/linux -shared Test.c -o libtest.so

Finally let the example run:

java Test

Finally some links:

-- ChristianS - 20 Apr 2004

 


InnerClasses  

21 Aug 2003 - 19:47 - r1.3   ArjanB

I was wondering if it will sometime be possible to declare inner classes in Nice ? I guess this is very useful in some cases. Inner classes are currently not accepted by the compiler. So I think the inner classes are not even planned ? (I come to this conclusion since public and private are in the list, but also not yet implemented, or am I wrong ?)

-- GamsL - 24 Jul 2002

Inner classes are one of these feature of which I am not sure if they would add anything to Nice. In this case my policy is to wait, work on what is surely useful, and listen to arguments. They are definitely in Java, but Java has no anonymous functions (which are faked by anonymous inner classes), and is class centric, so that it is useful to put a class inside another. Are there arguments to say that Nice misses them?

Actually inner classes in Java are compiled to normal classes, which have a link to their container class (roughly, I think there are visibility issues). Which gives a hint at what to do if you really miss one.

-- DanielBonniot - 25 Jul 2002

I find I use inner classes in Java quite often, usually when writing classes that need to work together closely and to avoid polluting the public interface or resorting to package access. The way I see it, inner classes are a combination of two features. The first is the automatic parent reference. While nice, this is just syntactic sugar and can be completely simulated in other ways. The second is the access granted to the private members of the parent class. This is essentially the same as using the friend keyword from C++, and as far as I know cannot be simulated in any other way in Java (beyond reflection, perhaps).

What I'd rather see in Nice though is something like the way Eiffel does access control. Every feature of a class in Eiffel can have a list of classes who (along with their subclasses) can see the feature. For example, the equivalent of protected access could be achieved by listing the class itself. A language feature like this allows classes to co-ordinate with each other at a very fine-grained level, rather than resorting to the big hammer of package access or the dangerous friend concept.

-- Vulcannis - 21 Aug 2003

Nice allows multiple classes in a single sourcefile. VisibilityModifiers are not implemented yet but the proposal is to give sourcefile access to things with the private modifier. So it will be possible to simulate the access restrictions as in java inner classes. Details of the access modifiers aren't decided yet.

-- ArjanB - 21 Aug 2003

 


JEditPlugin  

05 Aug 2004 - 16:18 - NEW   BrynKeller

I've started a JEdit syntax mode for Nice. Installation info and downloads are available from http://www.xoltar.org/2004/aug/05/jedit-nice-mode.html on my website. Comments welcome.

-- BrynKeller - 05 Aug 2004

 


NewEclipsePlugin  

03 Dec 2004 - 18:03 - NEW   MartinGamsjaeger

As I am just starting to develop a new Eclipse Plugin for Nice, I wanted to share my first ideas and goals concerning features and their realization with the community. Everyone reading this is very welcome to comment on everything that is said here! If you have ideas, feature requests, problems, you think I'm wrong, you think someone else is wrong, you know a better way to do something (maybe because you already have experience in that domain), really whatever comes into your mind concerning the nice-eclipse plugin! Don't be shy, post it here!

General Approach

One thing I have to say right away is that my general approach to writing this plugin may look a bit "conservative" to some of you, as I do not really plan to rush things and add feature after feature as fast as possible. Instead I'm planning to focus on a solid design that integrates smoothly into eclipse and is flexible enough to handle advanced IDE tasks . Therefore I still need to do extensive studies of eclipse to get more insight into how things are done. I know that it would be hesitating to start implementing cool editor features right away, but I think that without a solid architecture, a project of the size this one will probably have in the end, will be a pain to deal with.

One consequence of this approach is, that it may take some time until the first "true features" will be available (as building and running are too basic to be considered true features :-) . True Features are probably those that make editing Nice source easier. Another consequence is, that once the underlying architecture is reliable, it should generally be easier and faster to add features. I hope this will work out and provide a nice piece of software. Same as with everything here, comments welcome!

Goals

The following is by no means a complete list of goals for this project. These are just the ones that came into my mind so far (minus a few I just can't think of right now)

Long term goals

Long term goals haven't been defined exactly yet, but it is definitely an overall goal to provide a full fledged Nice IDE that supports everything programmers coming from java are used to. The general rule should be that if some operation is possible in the (Eclipse) Java IDE, it should be possible to do it in the Nice IDE as well, along with features we come across that are unique to Nice. This is a brave goal, it will take time to achieve it!

Short term goals

As said on page 18 of the german edition of the book "Contributing to Eclipse: Principles, Patterns and Plugins" by Erich Gamma and Kent Beck (maybe suffering from my poor translation abilities):

"Entering the world of Eclipse, you will spend more time reading code, than writing code. You first have to get used to those incredibly productive days, where you spend 6 hours on reading and 1 hour on writing code."

You probably guessed right, I own this book :-) Anyway, the following is what I will read a lot about, and hopefully also will write enough to make it work. Sections marked as DONE are still subject to refactoring or even rewrite from scratch, as I gain more understanding of the eclipse platform. So if you think almost everything is marked as DONE, why are these still goals? Think of the current implementation as a prototype that anyway will be rewritten in Nice very soon.

User Interface

Building

Launching

Design

This is actually the most important goal for now: get an understanding of the eclipse architecture to be able to extend it correctly and get the most out of it. It is very likely that the plugin will be developed in a few subprojects (that map to plugins) to separate logically independent parts from another. Here are two of them I can think of at the moment.

JVM Based Language Launching

As Nice compiles to java bytecode, Nice apps are run like normal Java apps. However, the eclipse code that realizes this functionality depends on the JDT's JavaModel? (a set of classes that model java source and - i think to a certain extent - bytecode as well). This leads to the restriction that plugins that want to launch programs using the JVM need always be JavaProjects? (working with a JavaModel?) in order to make use of the Java launching capabilities.

The goal of this subproject should be to provide a way for jvm-based languages to plugin their own type of project, along with their own model, and still use all the functionality and UI that Java programmers use when launching their applications. I think this makes perfect sense, as when it comes to launching, there is really no difference between java and nice (and probably most other jvm-based language). This idea came to my mind when looking at http://eclipsefp.sourceforge.net/ . Those people try to provide a common framework for functional languages (not especially targeted at launching) that should make life easier for plugin writers. Why not try to get something reusable out of a problem we anyway have to tackle?

A Model for Nice Source Code

To do advanced source code editing we need a model that represents Nice sources inside the plugin. This could be a model of source code that is constructed during a compilation, with a precise API to read and modify from the plugin, that can be sent back to the compiler for further (incremental) compilation. IMO advanced operations like refactoring, error correction proposals, searching, navigating, ... justify the additional complexity of such a model (and the changes/additions to the compiler that are needed), as they would be a pain to implement with no reliable infrastructure. This model (or API used by the model) could be implemented as a library using Nice AST. This is definitely one of the integral parts of the plugin and will need a lot of discussion, especially with core developers. Although it is no main goal for me at the moment to start implementing this, we should use the time to discuss an architecture both inside and outside the Nice compiler, that would be able to handle these issues.

-- MartinGamsjaeger - 03 Dec 2004

 


NiceCasts  

06 Jun 2003 - 20:26 - r1.24   AlexGreif

Here are some examples where I had to use cast or notNull in my project.

Which problems are not solved yet in 0.8? -- ArjanB


   java.util.List<Handle> handles = new ArrayList();
   ...
      ConnectionHandle ch;
      ch = cast(handles.get(handles.size()-1));
ConnectionHandle extends Handle

How do you know that the last element has the right type? -- DanielBonniot

The draggable points of a Connection are Handles. The first and the last are connected to flowlets, thats why they are called ConnectionHandles, and the handles in between are EllbowHandles. There can be zero or more EllbowHandles?. I defined it like this. -- AlexGreif

Interesting. Here it is the logic of the system that guarantees the cast will not fail. I think you could take into account this logic in the types. One possibility is to keep a reference to the handles on both extremities in fields of type ConnectionHandle. If you wish, you can encapsulate the handles in a Handle class:

class Handles
{
  List<Handle> handles;
  ConnectionHandle first;
  CollectionHandle last;
}
// Some methods to manipulate handles.
--Main.DanielBonniot

Interesting too. But IMO not very nice design, because the class Figure (the super class of all) has the member List<Handle> handles. And I want to store all handles in one List. A Connection has this speciality that it has two types of handles. Besides this I can iterate easily if all Handles are in one List. -- AlexGreif

OK. Then could you add in Connection the two fields, while keeping everything in the list? -- Daniel

Then the info is redundant, and I have to update both. Where do I profit if I introduce two fields? -- Alex

The type information is not redundant. A benefit is that you make sure that there is no cast, that might fail at runtime in some strange condition. On the other hand, it is true that you then need to guarantee that the value in the field is the same as in the list. If you have a set method in the parent to build the list, then you could override it to set the fields when the index is 0 or length - 1, and the call super.

I agree that the benefit is discutable. An alternative is to use the cast. In a future version of Nice, I could imagine that you could do:

Hand h = cast(handles.get(handles.size()-1));
assert h instanceof ConnectionHandle;
// Now you can use h as a ConnectionHandle.


      ?Figure figure = getFrontFlowWindowDrawArea().getDrawing().getFigureExcept(
                  mousePos, this);
      if (figure == null)   return;
      Flowlet flowlet = cast(figure);
Flowlet extends Figure

The problem is now like with ConnectionHandle?. Could you modify the design a bit, so that the type of the expression is Flowlet and not Figure?

No. Figure is the superclass of all drawable Items. Flowlets are items that can be connected together. Connections cannot be connected. Thats why they are Figures.

Here is the class hierarchy:
Figure <- PolygonFigure
PolygonFigure <- Flowlet
PolygonFigure <- Connection
-- AlexGreif


          if (connectorListeners == null)   return;
      for (Iterator<ConnectorListener> iter = notNull(connectorListeners).iterator(); iter.hasNext();) {
         ConnectorListener ltnr = iter.next();
         
         if (figure.getHandles().contains(cast(ltnr))) {
            iter.remove();
            //println(" deleted: " + ltnr);
         }
      }
Isn't this code equivalent to the following -- ArjanB

I think Arjan is right, I will test it -- AlexGreif

          if (connectorListeners == null)   return;
      connectorListeners.removeAll(cast(figure.getHandles()));

You need notNull, because connectorListeners is not a local variable. This is explained in OptionTypes. A solution is there too.

What is the type of figure.getHandles() ?

   java.util.List<Handle> getHandles() = handles;

ConnectorHandle, that extends Handle implements ConnectorListener

Interesting. So you have a value of type A, a List<B> with B extends A, and you want to know if the value is in the list, right? We were discussing with Arjan if this is ever needed. The point is, it can only be true if the value is of type B. But now I can believe this is really useful.

If it is really this, we will change the type of contains in nice.lang. After that, you won't need this cast. -- DanielBonniot

I changed the retypings so the cast isn't needed anymore in the next DevelopmentVersion -- Arjan

Another example to show why contains should be contravariant.

<T,U,V | U <: T, V <: T> Set<T> intersection(Set<U>, Set<V>);

intersection<T,U,V>(s1@Set, s2@Set) {
   Set<T> res = new HashSet();
   if (s1.size() < s2.size()) {
       for(U elem : s1) 
           if (s2.contains(elem)) res.add(elem);
   } else {
       for(V elem : s2) 
           if (s1.contains(elem)) res.add(elem);
   }
   return res;
}
Should I reapply that patch then Daniel? -- ArjanB

OK! Doesn't removeAll also need to get a contravariant type? -- DanielBonniot

Yes but if I'm consistent then should almost all methods of the collection be retyped to get a co/contra-variant type. the methods in Map will get uglier retyping then.

<K, K0, V0, V | K <: K0, V <: ?V0> ?V0 get(java.util.Map<K, V>, K0) =
  native Object java.util.Map.get(Object);

Yes, it makes sense. JSR 14 (Java Generics) does use Object for the key in get. So we are still more strict and safe than them.

I don't think it matters too much if the retypings become more complicated, especially if it means they will be usable in more situations. -- Daniel

Ok but I'm not sure about one kind of retypings:

<K, K0, V | K <: K0> java.util.Set<K0> keySet(java.util.Map<K, V>) =
  native java.util.Set java.util.Map.keySet();

this is safe because a keyset is read/remove only. -- Arjan

Are you not sure it is safe, or if it is useful? I checked the javadoc, it is true that you cannot add elements, so this must be safe. I'm not sure how useful it will be, but it does not harm to do it. Maybe it will turn out useful in some situations. And we can say that Nice allows this, while Java 1.5 cannot! :-) -- Daniel

It reminds me that I still should write something about retyping, at least the is no shortage of examples -- ArjanB


   getFromConnection(state) {
      java.util.List<Connection> followings = this.getFromConnections();
      
      for (int i = 0; i < followings.size(); i++) {
         DecisionConnection connection = cast(followings.get(i));
         if (connection.getState() == state) {
            return connection;
         }
      }
      return null;
   }
DecisionConnection extends Connection

Why don't you declare that this.getFromConnections() returns a List<DecisionConnection>? -- DanielBonniot

The code above is in DecisionFlowlet, but this.getFromConnections() is declared in Flowlet that returns Connection objects.

Is getFromConnections reimplemented for DecisionFlowlet? -- DanielBonniot

No. Only implemented in Flowlet class. Thus I have to return a List with the lowest common denom.. --Main.AlexGreif

Should I use :

      java.util.List<DecisionConnection> followings = cast(this.getFromConnections());
-- AlexGreif

It's possible, but that's still a cast.

Note that using get on a List in a loop can be bad, in case the List is a linked list: you will traverse n**2 elements, instead of n. This is ideal for the new for syntax of version 0.7.8:

   getFromConnection(state) {
      java.util.List<DecisionConnection> followings = cast(this.getFromConnections());
      
      for (DecisionConnection connection : followings) {
         if (connection.getState() == state) {
            return connection;
         }
      }
      return null;
   }
-- DanielBonniot

OOps did I miss that? Is it documented somewhere? -- AlexGreif

I think it's in the changelog only, at the moment. You see, Arjan, documentation is needed! :-) -- DanielBonniot

It should be in the manual that you need to look in the changelog. ;-) -- ArjanB

:-) Seriously, Arjan, you should write something to put in the Statements section. -- Daniel


more to come...

-- AlexGreif - 22 Apr 2003

OK, thanks. I'll treat them progressively.

For those that are solved, if you feel that some documentation should be added (for the numeric types, I updated the User manual, so that it compares with the Java syntax). After that they can be deleted.

Some will probably need to stay, when they are a good example of a typing problem, and how to solve it. So we can keep those there.

-- DanielBonniot - 22 Apr 2003

 


NiceCompiler  

30 Apr 2005 - 12:04 - r1.6   TWikiGuest

Implementation issues of the compiler.

Documentation

Building

 


NiceCompilerInNice  

12 Jun 2003 - 10:37 - NEW   ArjanB

When and how should the NiceCompiler(bossa.* packages) be converted to Nice? It has quite a few benefits but it will require a lot of time to do so.

Is the language complete enough to do this conversion? i.e. NiceConstructors?

What could be done to make the conversion easier?

-- ArjanB - 12 Jun 2003

 


NiceConstructors  

03 Feb 2004 - 09:42 - r1.35   DanielBonniot

Links to proposals

UPDATE: As a first step, in the current development version, classes can have initializers, like in Java.

One further improvement is to allow CustomConstructors. Comments are welcome about them.

See the latest ConstructorSyntax proposal.

Discussion

Nice doesn't have custom constructors but the default one is not always sufficient to express everything you want. The implementation of field depending on previous fields will help in some case.

In what cases are default constructor not enough and what could be added to Nice to solve that problem?

One possibility is to allow that each class can have one constructor without any arguments that is called after the fields are initialized and the constructor of the superclass is called.

-- ArjanB - 09 May 2003

Given that DesignByContract? is already part of the language, it's worth noting that using factory methods for object construction can cause problems with ClassInvariants. The invariant should be true on exiting a constructor, but need not be on entering, so some way of marking the factory method as for object creation is needed.

-- SamsonDeJ - 13 May 2003

One thing that might be wrong about Java constructors is that they serve two purposes. One is to assign values to the fields of the class. The other is to do any operation that needs to be done when an object is constructed. Let's call the first aspect construction, and the second initialization (are there clearer names, or are those clear?).

The problem with mixing these two purposes arises when you start calling methods from the constructor, before the fields are set. In other words, from a Design by Contract point of view, if you call a method before the invariant is valid. This means that the method called cannot assume the invariant is true. Worse, that method can call others.

How is this handled in other languages? In particular Eiffel, since it has contracts. If, as I suppose, all (public) methods can assume the invariant upon entrance, how is the above problem avoided?


Eiffel lets you mark methods as for instance creation, and these are not checked for the invariant at the start. There's a hack to allow them to call other (non-instance-creation) methods before the invariant is properly set:
invariant
   constructor_constraint: in_constructor implies [<a more limited invariant>) 
   general_constraint: not_in_constructor implies (<the full invariant>) 
so you set in_constructor and not_in_constructor at the appropriate places. It's got great potential for misuse though. To make it work you would have to painstakingly record for each method which parts of the class invariant they really depend on, which kind of defeats the purpose of an invariant. I've got a couple of vague thoughts on the matter, under ClassInvariants -- SamsonDeJ - 15 May 2003

My design goal in this area is to solve this problem, while keeping enough flexibility.

One possibility I see to solve this problem is to separate construction and initialization. They would clearly be marked as two different phases of creating a new object. Construction is already supported in Nice with the automatic constructor, where you provide values for each field (optionally for those with a default value). It might be useful to be able to define custom constructors, that construct the values of the field in other way, for instance with some computation over their parameters. But they would not hold a reference to the constructed object (this in a Java constructor), which solved the invariant problem. (A syntax would need to be created for those).

As for initialization, it could be done via a normal method, called for instance init. Because initialization can require calling arbitrary methods, the invariant should be true upon entrance (and therefore at the end of construction). It is a possiblility to choose to provide special support for initialization. In particular, we could make sure that init is called automatically when an object is constructed, and that the parent init (super) is called.


Doesn't this cause the same sorts of invariant problems as constructors in cases where the invariant depends on initialisation, not just construction? My suggestion (summarised from ClassInvariants) is to allow methods to be marked as either requiring the class invariant or not. Those that don't require it must still maintain it if it already applies, but may be called during initialisation as well as during normal operation. -- SamsonDeJ - 16 May 2003

The invariant is normally a condition on the values of the fields. In that case, anything that makes the invariant become valid belongs to the construction, not the initialization.

Yes, generally, but there are simple cases where this isn't so. For eg., how about a doubly-linked-list Node class. We would like the invariant

!hasPrevious() || (previous().hasNext() && previous().next() == this)
but that is only true after initialisation, since the constructor can't set the next field of the previous Node.

It could help to have a list of common things that needs to be done during initialization:


In this proposal, there could be several ways to construct the object, but the initialization would be a unique method. Comparing to Java where constructors, which serve both pruposes, can be overloaded, is this a limitation? I'd then to think that, besides behaving differently depending on the value of the fields, initialization should be uniform. If something else needs to be done in certain cases, then that can be done as a method call at the creation site.

A summary of this could be: creation = construction + initialization.

Does this sound like a nice and practical handling of object creation?

-- DanielBonniot - 14 May 2003

I'd just like to point out that I think the default constructor as currently provided is useful and should remain available.

_I agree with this. The default constructor will remain, as it is adequate for a rather large proportion of classes. Moto: Easy things should be easy, hard things should be possible. -- DanielBonniot

There are plenty of times, however, when I don't want people to use the default constructor. Mostly it's because I don't want them to assign invalid values to certain attributes. If I do:

class A {
  int i;
  ?int cachedCalculatedValue = null;

  int getCalculatedValue() {
    if (cachedCalculatedValue == null)
      cachedCalculatedValue = i * 5;
    return cachedCalculatedValue.notNull;
  }
}

I really need a way to keep people from doing new A(i: 5, cachedCalculatedValue: -23472398);.

I've been thinking about this for a while now, and I'm now wondering about a three stage approach. The code new A(...) works like this:

1. The arguments (...) get passed to the constructor method for A. "Constructors" don't actually construct anything, however, they just manipulate arguments. I'll call them "preconstructors" to differentiate them from Nice's current constructor. You might imagine preconstructors to look something like this:

//Using class A, above
A(int i) {
  //trim i to be <= 10
  if (i > 10) {
    i: 10;
  }
}
where the assignment i: 10 changes the value of i that will be passed to the default constructor. If no assignment is made, then the value that was passed in is used. The compiler calls all the preconstructors, from most derived to least derived. This ensures that a derived class cannot change the parameters to values which the base class's preconstructor would not allow. Preconstructors on a derived class can specify values for parameters in the base class, but which they do not themselves accept:

class Shape {
  int numberOfSides = 0;
}

class Triangle extends Shape {}

Triangle() {
  numberOfSides: 3;
}

However, preconstructors in derived classes can assign values to those parameters too:

class SuperTriangle extends Triangle {}

SuperTriangle() {
  numberOfSides: 9; 
}

numberOfSides will still be 3, not 9, because Triangle() runs after SuperTriangle?(). The double assignment should probably be reported as a warning. I'm not entirely sure about this, maybe it should be an error. Such a warning would have to be reported at the source location where the subclass preconstructor assigns to the parameter, to be useful.

2. The system calls the default constructor we use now, with the arguments returned from the preconstructor methods.

3. The system calls the 'init' method, passing the fully constructed instance.

As an alternative to this solution, here's a simplest-thing-that-could-possibly-work suggestion: allow to mark fields as off-limits to the constructor. Here's a syntax example, using a hypothetical 'internal' keyword:

class A {
  int i;
  internal ?int cachedCalculatedValue = null;

  int getCalculatedValue() {
    if (cachedCalculatedValue == null)
      cachedCalculatedValue = i * 5;
    return cachedCalculatedValue.notNull;
  }
}




and now doing new A(i: 5, cachedCalculatedValue: -23472398); would result in an error message like "A.cachedCalculatedValue is an internal field, and cannot be specified in the constructor".

Note that 'internal' is not the same as 'private' - internal fields may or may not be private, they just can't be specified in the constructor.

-- BrynKeller - 14 May 2003

This concern about the default constructor exposing too much is valid. It must be adressed.

Your first proposition is worth considering. However, my first take on it is that it looks quite complex.

The second is much clearer at first sight. Couldn't we go one step farther, by using 'private' for this purpose? I expect them to coincide extremely often. (In your example, you would probably want 'private internal'.) In cases where they don't, you can still provide a getter (and possibly a setter), or even use the property-like feature when it is added. The planned semantics for 'private' is that the visibility is limited to the file. So it comes naturally that you cannot refer to a private field in a constructor call, outside of the file declaring the class. Inside that file, you should be able to refer to it, for instance if you declare a custom constructor.

-- DanielBonniot - 15 May 2003

The default constructor which takes "any" variables is an interesting academic idea, but it's really ignoring the benefits of constructors.

With the Nice language's concept of the "sloppy default constructor", users will have to read comments to know what to provide (and those comments will get out of date) and we will have to have complicated DesignByContract? mechanisms in order to then allow class writers to enforce proper class construction.

Just add regular constructors. If you think that most constructors are simply instantiating all instance variables, please go take a survey of real-world code.

- DavidJeske

Hi David,

I've added comments in italics - DavidJeske

Thanks for your contribution. We are well aware that having only default constructors is not the perfect solution yet. In particular, we know that instantiating all fields is not the only way to use constructors. By allowing users to construct objects with "whatever fields they want" you are placing an unnecessary burden on the object-author to handle unknown initialization cases, and on the object user to figure out what the useful initialization cases are

First, let me explain why "regular constructors" are not perfect either. The most obvious problem is that they are inherently unsafe. They allow you to refer to this inside the constructor, even before the object is completely constructed. This is alot saver than not knowing whether or not the user will suppily enough fields to construct the objects, because you have no control over the constructor AT ALL.

Here is a simple example, in Java:

class Parent {
  Parent() {
    // We want to log the construction of Parent objects
    Logger.log("Instance created: " + this);
  }

  public String toString() {
     return "Parent";
  }
}
Is this class correct? One would easily think so. And indeed, it will work properly by itself. Now imagine a subclass is created:
class Child extends Parent {
  /** @file a non-null File */
  Child(File file) {
    this.file = file;
  }

  private File file;

  public String toString() {
    return "Child, with file: " + file.getCanonicalPath());
  }
}
Apparently, we did nothing dangerous. First thing done in the constructor is to set our private field. We require that the given file is non-null. So toString should never fail with a null pointer exception, right?

Well, it will. This is because the parent constructor is called before the child constructor. And the parent calls toString, when the file field is not set yet. Boum!

I fail to see how Nice's "no constructor" system fixes any of this. In Nice, the user might supply zero paramaters to the constructor, and then what do you have?

So this inocent looking, two class example fails. I think many developers would not spot the bug if they were just given the source. Probably, after the bug is revealed, they will find it in not much time. But what about more complex examples, involving large hierarchies of classes?

This is why we want to think about alternatives to "normal constructors". We are convinced that a better design is possible. Okay, I'm all for that, but the current step Nice has taken is a step back IMO. I'll have to think about class factories, and other things and get back to you with some better suggestions

Now you have a very good point, which is that even if we try to improve some aspects, we should not go backwards in others. Here is a tentative list of desired features:

I think this is achieved by two means. First, it will be possible not to export the default constructor. I don't understand why I would ever want to export the default constructor Second, if a class used to export the default constructor, and you want to change the implementation without changing the interface, you can hide the default constructor, and define a custom constructor with the same interface, that does the appropriate construction internally.

One last point that should be mentioned: it is planned to allow fields to be declared as public-read, which means they can be read publicly, but not writen to (read access being either package, or private). I like this feature Furthermore, it is possible to replace such public-read fields with a methods, without changing the interface of the class. This is fantastic! This feature lifts two of the main reasons that public fields in Java are considered bad, and should be avoided. Even though public fields should not be used, I don't see any reason to discourage the use of public-read fields. I even like the idea of public write fields if you can do the same trick where they can transparently be values or methods. This is like C# properties without the interface-breaking change from a field to a property. This is how it should have always been done. We have all this fancy runtime JIT stuff, we should be USING it for something.

A few answers to the comments. First let me restate that we are discussing future design. The default constructor is not in itself the solution to these problems. In the final design, the class designer will have complete control over the construction interface.

We'll be glad to look at your suggestions about class factories. Also, could you provide an example of the problem with C# change from field to property?

It's great to have input from different people. This really helps the reflexion, and should lead to a better design in the end :-)

-- DanielBonniot - 19 Jun 2003


From: DavidJeske - 19 June 2003

Here are some thoughts:

public fields

Code readability is easier if accessing public fields uses assignment syntax (a.foo = 1 instead of a.setFoo(1)) C# addresses this by adding "properties". This is a special syntax for get/set methods which yeilds class members which look like fields and act like methods. Here is an example:

class Foo {
  public int count {
     get { return count; }
     set { count = value; }
  }
}

However, this creates confusion for developers:

Ideally, the developer could start with a field, and later migrate to having a method implementation behind the field without changing the classes interface. Since JVMs and CIL both use really-fancy JIT compiling, the "null case" for the method implemention should be easily inlined out when there is no implementation.

class factories and flexibility

Class factories are a useful feature where downstream code can control how other code allocates objects. Just like an application re-uses the code of a library from above, by replacing the code beneath a library you can augment or repurpose that library.

Very useful tools make use of this functionality, but they normally have to go through gyrations to do it. For example, malloc-debug can sit underneath your code and tell you useful things about memory allocation. A debug version of glibc can have instrumentation code which isn't in the normal version. You can see this pattern in effect inside many places in Java. One such place is the socket libraries. Even though you don't have control over the creation of sockets when using the JavaMail IMAP support, you can get it to use SSL for the sockets instead of normal sockets. You do this through an ad-hoc mechanism involving the string names of the classes you would like the factory to use. Here is an example:

final String SSL_FACTORY = "simpleimap.DummySSLSocketFactory";
// Get a Properties object
Properties props = System.getProperties();
props.setProperty( "mail.imap.socketFactory.class", SSL_FACTORY);
props.setProperty( "mail.pop3.socketFactory.class", SSL_FACTORY);
props.setProperty( "mail.imap.socketFactory.fallback", "false");
props.setProperty( "mail.pop3.socketFactory.fallback", "false");
props.setProperty( "mail.imap.port", "993");
props.setProperty( "mail.imap.socketFactory.port", "993");

There are several problems with the JavaMail mechanism which are common to other implementations:

Ideally any object allocation would be controllable by providing built-in configurable object factories at the language level. One possible implementation would be to require that all allocated objects be "class fields" at the class or module level. By providing alternate classes to the class fields, the object would allocate and use a different implementation.

Someone out there is ready to jump up and down and say that "parametric types are the solution"! By providing a parametric SocketType? paramater, a library can easily allow me to override the socket type which is created by my class. Parametric types only solves one of the problems I listed above. The first and most important problems still exists, namely that if the original class designer did not think to make it parametric, then it's not possible for me to do so later.

Perhaps there is a deeper relationship between class factories and parametric types which can be created which will be sure that this paramaterization is always available. For example, perhaps we can implicitly make classes which are allocated in a class part of the paramaterization of that class. Here is a not too well-thought out example:

This code fragment:

class IMAP {
  Socket conn;
  IMAP(String server) {
     conn = new Socket(server);
  }
}

Would be automatically converted into:

class IMAP<S1=Socket implements>
  Socket conn;
  IMAP(String server) {
     conn = new S1(server);
  }
}

-- DavidJeske - 20 Jun 2003

Java compatibility

One thing to consider is that, since there are many more Java programmers than Nice programmers, it should be possible to write libraries in Nice whose intended audience is Java programmers. Ideally, the compiler output would be a jar file and javadoc that look as if they were written in Java. So it would be useful to be able to write constructors that appear in Java to be ordinary Java constructors.

-- BrianSlesinsky - 21 Nov 2003

That's a good point. Default constructors are already compiled as ordinary Java constructors, and can be used as such. I believe it is also possible to compile CustomConstructors as ordinary Java constructors. One difficulty comes from overloading based on argument names: if you have both new Point(double x,double y) and new Point(double angle, double distance), then both cannot be compiled to a Java new Point(double,double) constructor: that would be ambiguous since Java cannot make a distinction based on argument names.

-- DanielBonniot

Getting rid of boilerplate constructor code is fine; although, as noted above, we may just have moved the workload from writing the constructor to updating parameter names at the call site (after changing class variable names).

Not really, because with CustomConstructors you can keep the constructor API even if you decide to change the field names. And if the old names do not make sense at all anymore, then likely it means that you are changing their semantics, so the clients would better be aware of the change (like changing x,y into angle,distance).

Could we avoid that issue by providing parameters in the class definition? This Scala example might fit with Nice's labelled parameters.

-- IsaacGouy - 27 Jan 2004

Isn't the issue solved by CustomConstructors? In Scala, it the constructor arguments are not labelled, which means you cannot precise the meaning of the values you pass.

-- DanielBonniot - 27 Jan 2004

Linking field names, to the constructor (and then being forced to use those field names in the constructor call) feels wrong to me. Seems better to have labelled constructor arguments - and have the programmer take responsibility for setting the fields to the argument values. (Like Scala but require the labels to be used in the constructor call.)

Are there Nice features that rely on there being a custom constructor?

-- IsaacGouy - 27 Jan 2004

We don't absolutely link field names to constructors, we just make that the default, and give you the tools to change it easily if you want or need.

If you want to have another behaviour, it will be possible: mark the default constructor as private, and write a custom constructor which sets the fields. My idea is that in many cases the default constructor will be sufficient and natural, so you don't need to put effort into doing it yourself, obfuscating (ever so slightly) the source. Doesn't having scores of x = this.x; in Java or var x: Int = xc; in Scala feel like a hack?

Something you cannot do with the Scala approach is to have a Point class with both interfaces new Point(x:..., y: ...); and new Point(angle: ..., distance: ...);. You could have either (and they would not need to match the internal representation), but you cannot have both. This means you cannot hide some representation choices to the clients even if you decide too, and you cannot provide an backward compatible way to upgrade the construction API of your class. So you are back in the case where you should always write factory methods, just in case...

-- DanielBonniot - 28 Jan 2004

We don't absolutely link field names to constructors, we just make that the default And it's a default I will in every case over-ride! I don't like writing x = this.x; but I really hate having field names public. Hey I have something in common with Bertrand Meyer ;-)

This is just about the only thing in Nice that I actively dislike.

-- IsaacGouy - 29 Jan 2004

Isaac, are you sure that the reason that you hate them is not because, in Java/whatever, they expose an implementation detail that cannot be changed afterwards? Can you give a reason why they would be bad in Nice with this proposal?

I would be very glad to know you dislike nothing in Nice :-) -- DanielBonniot - 30 Jan 2004

Can't this be solved by VisibilityModifiers? You could say that the implicit constructors are package-private by default. Then you don't have to worry about the fields of a class being exposed in the public interface. Or, if implicit public constructors must be supported then their interface is defined by the public fields of the class. If you have non-public fields then you must write a CustomConstructor?. Public fields would presumably still be exposed as (implicit) getter/setter methods outside of the package defining the class. -- BrianSmith - 29 Jan 2004

Sorry, Brian, I'm getting confused. Are you answering to Isaac or to me? What is "this" that would be solved? -- DanielBonniot - 30 Jan 2004

"this" = "the problem of exposing implementation details (non-public fields) via constructor parameters." If non-public fields are never exposed in constructor signatures then it seem to support Isaac's request while still "getting rid of boilerplate constructor code" in many (most?) cases. -- BrianSmith - 30 Jan 2004

The visceral reaction is because they expose implementation detail period. Done so much of that pure object Smalltalk stuff that exposing implementation detail is a last-resort, special-case, optimization kind-of-thing. Definitely not a default case, every constructor kind-of-thing.

Or maybe it just seems ugly to have _aa as a constructor label ;-)

   class A {
      private int _aa;

      int aa() = _aa;
      int aa(int x) = _aa = x;
   }

   void main(String[] args){ 
      let a1 = new A(_aa: 2);
      println( a1.aa );
   }

And that was actively dislike, there may be other things ;-) -- IsaacGouy - 02 Feb 2004

Isaac, I am having trouble understanding your last comment. Wouldn't your objection be solved by making the implicit constructor for every class package-private by default? Then, code outside the package cannot access the constructor at all, regardless of the visibility of the fields. In your example, it seems that main would be able to see the _aa field anyway because it is defined in the same package, so you don't need the two methods named aa. If you moved main to another package then you wouldn't be able to instantiate class A at all without writing a custom public constructor or a public factory method. So, it seems like my idea supports your request? -- BrianSmith - 02 Feb 2004

Isaac, we all agree that implementation details should not be exposed. Again, in Nice with the current proposals (CustomConstructors and PropertySyntax), no implementation details will be exposed to clients, so there is no reason not to use public/package fields.

For instance, for you example you can simply write:

   class A {
      int aa;
   }

   void main(String[] args){ 
      let a1 = new A(aa: 2);
      println( a1.aa );
   }

If later you want to change the implementation of A so that aa is not a field, you will be able to do it, without changing the API of the class.

-- DanielBonniot - 03 Feb 2004

 


NiceConverter  

23 Jun 2005 - 00:11 - NEW   TWikiGuest

It would be nice to have a tool to convert a set of Java classes to Nice syntax (e.g. stripping out the typecasts, putting argument names in all method calls, etc.). Even if it only did of the job, it would still be useful as a head start on moving an existing project from Java to Nice. For reference, see the tool that Apple provided in WebObjects? 5.1 for converting projects from Objective-C to Java:

http://developer.apple.com/documentation/LegacyTechnologies/WebObjects/WebObjects_5.1/JavaConverter.pdf

-- TWikiGuest - 23 Jun 2005

 


NiceDoc  

13 Sep 2003 - 04:10 - r1.6   DanielBonniot

We need a javadoc-like tool for Nice. If possible, it would be good to re-use someone else's existing backends and just write a frontend for Nice.

-- BrynKeller - 26 Jul 2002

A more general problem is parsing. Good parsing tools will be needed for NiceDoc and also for the EclipsePlugin. I have to say in general I like ParserCombinators better than lex/yacc - style parser generation. Anyone have such a library already?

-- BrynKeller - 25 Apr 2003

Not that I know about. Writing one in Nice could be a good test/exercise. Other options for parsing in NiceDoc: write a parser using an open-source parser generator like ANTLR, or reuse the existing JavaCC? parser used in nicec.

-- DanielBonniot - 06 Jun 2003

Following on the idea of reusing parts of the compiler, I have started improving the compilation API to make that possible. The current version (0.9.2) of the compiler offers an API to load the source of package, without generating code, but instead returning a list of packages, each one containing a list of the toplevel definitions in the package. I put together a demo for this feature, which could be the embryo of NiceDoc. You can get the source here.

-- DanielBonniot - 13 Sep 2003

 


NiceLogos  

02 Aug 2003 - 09:22 - r1.5   DanielBonniot

Chetan Mittal

Chetan Mittal

Nice work! It might be good to keep some visual identity, though. Is it possible to do a small version of the first logo, that would be suitable for eclipse? It would just have the 'Ni' part (if I read the logo correctly :-).

(You should register as a Wiki user. Then you don't have to put your email on each page. And that will also allow you to get email notification when the wiki changes).

-- DanielBonniot - 01 Jun 2003

 


ObjectType  

15 Dec 2003 - 13:24 - r1.3   DanielBonniot

This page documents the support of the type Object in Nice, which has been present since version 0.9.5

Current Situation

Object is currently a sort of alien in Nice. It is not a super type of all types, nor of all class types like in Java. This is the case because in most situation your are better off using type variables. When using a Java library that uses Object in its API, it's usually best to use a retyping to give it a proper strict type.

It would also make the type system weaker to have a global super-type, because for a method declaration like:

<T> boolean `==`(T,T);
we want "ABC" == myFile to be a type error. If Object was a proper type, it would not be the case.

So currently, Object is an accepted type in Nice, but it is not related to any other type. One can convert a value to have type Object by using the method object(...).

Proposal

There are still reason why we might want to add more support for Object. To avoid the problem noted above for methods like ==, Object would not be a proper type, in that type variables cannot be instantiated to Object. On the other hand, it would be consider as a top type, which means that any type is a subtype of Object.

Motivations

Let's see what benefits this would bring.

Principle of least surprise

Currently, the Nice compiler can report:

Incorrect type in assignment to o
Found   : java.lang.String
Expected: java.lang.Object
Even when superior solutions exist that do not involve Object, some newcomers to Nice will sometimes try to use Object. In this case, it would be better to have a less surprising behaviour.

Note that with Nice's dynamic type inference, even when using Object you can avoid casts:

Object f = operationReturningAnything();
if (f instanceof String) {
  // f has type String here, no cast required.
  int len = f.length(); // String operation, resolved at compile time.
  ...
}
So even without using more advanced features, users can get typing benefits when moving from Java to Nice.

Legacy libraries

For Java libraries that use Object, the best thing to do will most often be to provide retypings. Still, this proposal will ensure that even without retyping, the typing will be sensible and unsurprising, like in Java.

Moreover, there are some libraries wich use Object to represent some heteregeneous set of classes (for instance, a value that can be eith a String or a File). While this design is very questionable, these cases still occur. The proposal would make it more natural to handle such cases.

Heterogeneous data structures

If for some reason, you need to put unrelated types in an array or a collection (for instance to pass it to a Java library), you could declare it as Object[] or List<Object>, and put any value in there.

Typing reflexion

Currently, reflexion operations are typed polymorphically. This means that you don't need explicit casts when using reflexion. However, if you want to read an arbitrary value by reflexion, the only safe type you can give for a local variable that holds that value is Object. If you want to also assign a known value to that variable (for instance a default value), then you need this proposal.

Unknown type

This is a generalization of the previous case. If for some reason you need to use an unknown type, Object needs to be used. It is only better to have the information that any value can be assigned to that variable.

-- DanielBonniot - 17 Nov 2003

 


PackageRepository  

23 Aug 2004 - 18:29 - r1.5   BrynKeller

This is a draft about how package repositories will be handled. Some motivation for this feature is given there.

Principle

A repository specifier can be placed somewhere on the classpath (typically at the end). This means that if there is import some.pkg; in the source, and that package does not exist locally, it we be looked up in the repository. If it is found, the jar file for the latest version is downloaded, and stored in a cache. Then everything happens as if that jar was on the classpath.

There will be an official repository at http://packages.sf.net/repository/, and it should probably be included at the end of nicec's classpath by default.

Cache

The cache can be shared between projects, since jar filenames include a version number. The cache must be created somewhere the user has write access to, so on unix it would be in ~/.nice-repository/ (~ being user.home). What about other platforms (windows)? Is user.home always a good place?

Versioning

Once a project starts to use a version of an imported package, that version should stay the same until explicitely requested. Therefore, the version number must be stored somewhere. At the moment it's in a file nice.versions in the current directory. It contains lines of the form some.pkg:version. This file should be commited to the source code repository (e.g. CVS) for the project, so that every developer uses the same version, and that upgrades are tracked.

Explicit upgrades should be possible, for instance by edition of the nice.versions file. In addition, there could be a tool that tries to automatically upgrade imported packages to their newest version. After getting the new versions, it would try a compilation then unit testing. If all goes well, then the nice.versions would be automatically updated.

Publication

This is about creating packages and uploading them into a repository. First, a version number must be chosen. There is a manually chosen prefix, and an automatically attributed suffix. The prefix could be specified in the nice.versions file in the entry for the package itself, and default to 0.0 if absent. The suffix would typically be a representation of the UTC date and time, so it grows over time. This allows several versions of a package to continue to evolve in parallel. Changes of the prefix could be done when an API or behaviour change needs to break backward compatibility, and automatic upgrades would not cross those version changes.

Once the jar is created, it needs to be uploaded to a repository. Version a.b.c for package foo.bar would be located at foo/bar/foo.bar-a.b.c.jar inside the repository. It can be =scp='ed manually there. A small publication program can automate this. The question is whether it's worth to include a Java implementation of ssh (jsch is 84K in jar format), or rely on ssh/scp being installed on the system.

Alternatively, it's probably a good idea to promote continuous builds of published packages. It's especially important when packages start to import each other: you need to make sure they can use the latest versions, otherwise it will become difficult to find compatible versions. We have CVS space on package.sf.net, so we could encourage people to put libraries there. This would open the possibility to have discussions for package names, to make sure there is some coherence. Then we can install a single continuous build script, which would be triggered by CVS commits, and rebuild everything that needs to, then publish the resulting packages if they work. This is where the date suffix in versions becomes particularly handy.

Ideas, questions?

Comments are welcome.

-- DanielBonniot - 02 Aug 2004

Definitely need a java version of ssh, as ssh/scp are most definitely not available on Windows machines, and it can be a bit of a chore to find one that works the way you want without a lot of configuration difficulties.

I'll write some more later when I've had a chance to review in more detail.

-- BrynKeller - 04 Aug 2004

About ssh, the question is whether if we expect people to upload new versions manually. As I said in the part about pulication, it might be a better idea to rely on continuous builds, in which case it's not a big deal to expect ssh to be present, at least for the time being.

-- DanielBonniot - 23 Aug 2004

Ah, okay. I'd vote in favor of continuous builds, then.

-- BrynKeller - 23 Aug 2004

 


ParserCombinators  

25 Apr 2003 - 18:44 - NEW   BrynKeller

Parser combinators are a functional approach to parsing that uses a combination of functions to define the grammar. Some (like me) find that this leads to a pleasantly natural expression of the parser. Also, it means you can write your parser entirely in the host language (Nice, e.g.) rather than having to learn a new, specialized language for your parser generator.

Haskell examples:

-- BrynKeller - 25 Apr 2003

 


PartialApplicationSyntax  

24 Feb 2004 - 18:11 - r1.14   IsaacGouy

Imported from SourceForge? RFE #672069

Background:

Many functional languages provide "curried" functions, of the form a -> b -> c, rather than the more typical (in Nice) (a,b) -> c. I think providing curried functions by default causes much confusion (and obscure error messages), so I think Nice's approach is good. But curried functions are often handy too.

Feature:

It would be good to have a compact syntax for partially applying a function. I'll suggest '_' and '...' as the symbols to use, where '_' means "omit this argument" and '...' means "omit all remaining arguments". So, for example:

String greet(String salutation, String adjective, String object) = salutation + ", " + adjective + " " + object;

test()
{
   (String, String)->String helloFun = greet("Hello", ...); //Fill first param only
   String->String helloWorldFun = helloFun(_, "world"); //Skip first param
   String message = helloWorldFun("currified"); 
   println(message);         //prints "Hello, currified world"
}

Which would be equivalent to:

test()
{
   (String, String)->String helloFun = (String adjective, String object) => greet("Hello", adjective, object));

   String->String helloWorldFun = String adjective => helloFun(adjective, "world");

   String message = helloWorldFun("currified");
   println(message);    //prints "Hello, currified world"
} 
-- BrynKeller - 13 Feb 2003

I like this idea of using '...' for curried function. There is a good chance it will get in before 1.0 . But I'm not sure about using '_'. An alternative for '_' is using named parameters as in this example:

String greet(String salutation, String adjective, String object) = salutation + ", " + adjective + " " + object;
let (String adjective, String object)->String hello = greet("Hello", ...);
let (String adjective)->String helloWorld = hello(object:"world", ....);

test()
{
   String message = helloWorld("currified"); 
   println(message); 
}

-- ArjanB - 03 May 2003

That sounds like a better solution to me. We need a something for when the parameter names are not known, however:

(int,int)->int partialApplicator((int,int,int)->int theFunction)
{
  return theFunction(_,5,_);
}

A better solution might be to allow to name the sub-components of the function type:

(int,int)->int partialApplicator((int a,int b,int c)->int theFunction)
{
  return theFunction(b: 5, ...);
}

... or to allow arguments to be referred to by number (starting from 0 in this example):

(int,int)->int partialApplicator((int,int,int)->int theFunction)
{
  return theFunction(1: 5);
}

I think I prefer the naming syntax over the positional syntax.

-- BrynKeller - 05 May 2003

I like this idea of using '...' for curried function

Couldn't the naming syntax apply to this also?

String hello(String adjective, String object) = greet(salutation: "Hello"); 

From calls to agents presents a very general mechanism that has been introduced into Eiffel.

Here's another syntax for Currying, multiple parameter lists modN(n: Int)(x: Int) = ((x % n) = 0);

-- IsaacGouy - 20 Jan 2004

I think this last syntax is not special, it's just what you get when you define a function with multiple arguments as a function taking one argument and returning a function. That is, you could already do this in Nice:

int->boolean modN(int n) = int x => (x % n) == 0;

OK, we could accept the syntax modN(int n)(int x), but I'm not sure it brings much. -- DanielBonniot - 21 Jan 2004

Isn't this syntax just implicit curry, a la ML or Haskell? This is exactly what I don't want to see in Nice, I think explicit currying is better. I think it needs to be easy, but not implicit.

-- BrynKeller - 22 Jan 2004

Yes, it's a form of implicit curry. Note that we could perfectly have both:

int modN(int n, int x) = (x % n) == 0;
int modN(int n)(int x) = (x % n) == 0;
The second line defining a curried function. I don't think that would hurt, since uncurried versions would likely stay the "default". This would just be an easier syntax to define named curried functions. I just think that the PartialApplicationSyntax is more prioritary, but I don't think this syntax for curried functions is incompatible or would hurt in any way.

-- DanielBonniot - 23 Jan 2004

While we're discussing syntax, is there a rationale for using -> in the type but => in the definition? Would it be reasonable to use one of those in both places?

int->boolean modN(int n) = int x => (x % n) == 0;
-- IsaacGouy - 01 Feb 2004

Yes, that's a valid remark. I think in that case we should settle on -> for functions, which would allow to use => for logical implication. Is there a consensus on this change? -- DanielBonniot - 02 Feb 2004

I think I objected to this suggestion a while ago, because things could get confusing with anonymous functions:

[ `+`, `*`, `-`, `/`].map( (int,int) -> int func -> func(4,5));

but on the whole I'm not really convinced of this danger anymore, and parentheses can always be used if clarification is necessary. I'd go along with getting rid of => for functions.

-- BrynKeller - 03 Feb 2004

Mildly amusing that Scala chose to use => for both and we seem to be chosing -> for both. -- IsaacGouy - 24 Feb 2004

 


PerformanceTesting  

07 Nov 2003 - 12:10 - NEW   DanielBonniot

We already have a comprehensive TestSuite, to check the correctness of the compiler. It would also be very useful to be able to automatically mesure performance. This falls into two categories: performance of the generated code, and performance of the compiler itself (compilation time). These tests would help make sure that new versions of the compiler do not degrade performance, and when we work on optimizations that they indeed improve performance.

-- DanielBonniot - 07 Nov 2003

 


PropertySyntax  

12 Nov 2003 - 21:24 - r1.8   DanielBonniot

I was thinking if it maybe would be a good idea to let the compiler help when writing properties. What if we could let the compiler automatically create get/set functions in the same fashion it does with the automatic constructor ?

Of course it is not sufficient to generate get AND set all the time, but we could use keywords like

We could then declare fields like:

class Test
{
  private read String someString;
  private readwrite int someInt;
}
and then be able to call getSomeString() but NOT setSomeString(s) (the compiler knows that set is not defined since someString is only read'able)

Another idea (I like even better) would be to then be able to write

Test t = new Test
 (someString: "Test"
  someInt: 3
  );
println(t.someString)
//but NOT
//t.someString = "AnotherTest";
A problem that I see with automatic generation of this methods (operators) is that there should be a way to override them ! This makes me think of the way C# handles properties (very nice I think)

in C# you can write:

class PluggableContainer
{
  private SystemState state;

  public SystemState State
  {
    get
    {
      // found no actives and no inactives at the beginning
      bool foundActive = false;
      bool foundInactive = false;
      // loop through all IPluggable objects
      foreach(IPluggable pluggable in items)
      {
        if(pluggable.Active) foundActive = true;
        else foundInactive = true;
      }

      // try all possible combinations
      if(foundActive && foundInactive) this.state = SystemState.PartlyActive;
      if(foundActive && !foundInactive) this.state = SystemState.Active;
      if(!foundActive && foundInactive) this.state = SystemState.Inactive;
      if(!foundActive && !foundInactive) this.state = Systemstate.Error;

      return state;
    }
    set
    {
      if(value == SystemState.Active) SetState(true);
      if(value == SystemState.Inactive) SetState(false);
    }
  }
}
value is implicitely generated and contains the value to set (always the same type as the field)

So what about a combination of these ideas ? we could generate the methods with default behaviour, if more special instructions are needed we could override them.

The compiler could then (somehow:-) know that when he sees a Person.getName method he can also use String s = p.name but not p.name = "gamsl" since he knows no setName method ...

Knowing nothing about compilers and language design in general .... what do you guys think :-)???

-- GamsL - 20 Jul 2002

In my experience, I have found that protected fields have the same problems as public fields in classes. That is, once you set a field as protected, you are no longer able to control access to the fields by subtypes. What I would like to see in the language would be that all fields default as private. If the user wants to make a field protected or public he would override the method with their implementation. An example:

class PropertySyntax{
     private String property1;
}

would be transformed by the compiler to:

class PropertySyntax{
     private String priv_property1;//this variable would not be reachable by the user of the language. If the user wants to set or get the value, they need to use the methods provided
     private String property1();//the get method
     private void property1(String property1);// the set method
}
//default get implementation
property1(syntax){
   return syntax.property1;
}
//default set implementation
property1(syntax,property1){
   syntax.property1=property1;
}
Now if the user provides their own methods to the class then those methods should be used instead of the default ones. So lets say I want to make the get method public and change the implementation of the set method but keep it private.
class PropertySyntax{
    private String property1;
    public property1();
}
//since I have not specifed an implementation of property1(); the compiler will auto-generate the method but with public access instead.
property1(syntax,property1){//no need to declare this in the class since the signature is assumed by default
   super;//call the super classes version. Or in the case of private or base class use the default version
   //do stuff
} 

now when the user of the class wants to get the field they should be able to do it 2 ways:

PropertySyntax syntax=new  PropertySyntax(value);
//method syntax
syntax.property1();
//or the can use field syntax
syntax.propert1;
//althought the example above does not allow setting. if it did you would have the following
//method syntax
syntax.property1(value);
//field syntax
syntax.property1=value;
The advantage to the above approach is the following:
  1. no need to change the syntax of the language.
  2. enforces good OO practices by keeping fields private.
  3. Field syntax makes it as easy to set fields as it would be if the field were public.

Thoughts and questions welcome.

ArthurSmyles 23 Mar 2003

I think a decision about this should be taken soon since details of others things like constructors depend on this.

-- ArjanB - 03 Jun 2003

Could you describe how they depend on this? What would be the consequences?

-- DanielBonniot - 04 Jun 2003


I don't know what's been decided on this, if anything. But I'm generally in favor of the ideas propsoed above, especially those by ArthurSmyles. I like the C# solution, though I'm not stuck on the syntax. The goal is that all code outside of a class should not know or care if a member is implemented directly accessible, or hidden behind a method or methods. That allows for the greatest degree of refactoring by the class implementor in the future, by lowering the degree coupling, which is always a good thing in large projects.

-- TroyHeninger - 12 Nov 2003

What is holding this back is mostly the lack of manpower. We will get to implementing it eventually, but the more people are willing to contribute, the faster things will move. Would you be interested in helping (with this or another aspect)?

-- DanielBonniot

 


StandardLibrary  

02 Jul 2005 - 10:04 - r1.17   TWikiGuest

Documentation for the standard library

We need a documentation for the standard library. The best way would be to write a tool NiceDoc, similar to javadoc. There are already documentation comments in the library. Writing nicedoc is a project in search of a volunteer to start it!

Unsupported operations in Java collections

Another thing I've been struggling with, is that the current collection hierarchy is somewhat imprecise - Collection specifies a number of operations which commonly appear together, but which might not always be appropriate (e.g., it's debatable whether LazyVector? should have a size method), and the same is true of sequence. I'm toying with a much more granular hierarchy at the moment, which I'll detail later. It also has two hierarchies, one for collections which allow in-place modification, and one for collections which do 'functional update', that is, return copies of themselves with the changed values. More later. -- BrynKeller - 05 Aug 2002

I also have concerns with this UnsupportedOperationException. It seems that the interface hierarchy was not well designed. Anybody interested to propose a fixed hierarchy?

-- DanielBonniot - 09 Sep 2002

Here a page discussing this problem: http://jinx.swiki.net/87

see also FlagInterfaces for an experimental approach to solve this problem -- ArjanB

Additional collection methods

see also StandardLibraryMethods

Are the methods in the StdLib? a complete set of additions to the collections api or do we need more?

A few names of the methods could be could changed to fit better the java parts of the api. has->contains, keep->retain and "find" shouldn't throw an exception. -- ArjanB

I added contains and retain in CVS, and made has and keep deprecated. We will remove them in the future, preferably waiting some time after the compiler starts emiting warning when using deprecated methods. I also renamed findIndex into indexOf, do we agree on that too?

About find (and findLast), there are two versions. One works only on collections of non-null values, and it returns null if no element was found. The other one works on any collection, but throws java.util.NoSuchElementException is no element was found. So you can choose your style: either checked the returned value, or handle an exception. The advantage is that there is never confusions between a null element in the list passing the test and no element being found. What is the problem with this approach?

It might be practical to give the two versions different names, so one can really choose which one to use in every case. I thought about find and search. The idea is that find is expected to always return a value. If it doesn't, it is exceptional, so it throws and exception. On the other hand, search is merely searching for something, which might not be there (in which case it returns null). Comments?

-- DanielBonniot - 10 Jun 2003

Are the methods in the StdLib? a complete set of additions to the collections api or do we need more?

I think there's room for a lot more collections methods in the standard library - in fact I'm working on some now, hopefully I'll be ready to circulate them for comments some time in the next two weeks.

-- BrynKeller - 11 Jun 2003

Can you give a preview of what you have? If you are short in time, I could help implementing the additions.

Have you considered the addition/overloading of operators for common operations on collections? I think of an operator for creating ranges.

-- ArjanB - 29 Jun 2003

About "throws Exception" or "return null", I choose both in a similar problem without change the name of the method. My suggestion is to provide 2 methods find(<K> key) (throws NoSuchElementException? if not found) and find(<K> key, <V> defaultValue) (return defaultValue if not found), like this no method name confusion (and always need to remember wich one throw the Exception), and you could store/find 'null' value and use an other defaultValue. An other variant is to define a property of the Collection to tell if you want to throws Exception or return a defaultValue.

-- DavidBernard? - 02 Jul 2005

Support for 'break'ing in foreach

I've noticed that there's a need for another basic method on Collection, which is a method that's like foreach, but provides the client code with some way to stop the iteration. I'll call this method forbreak, because it's foreach with a break. It looks something like this:

<Any T> void forbreak(Collection<T> coll, (()->void)->T->void func);

forbreak(s@Sequence, func) {
  boolean breakFlag = false;
  T->void each = func(()->void esc =>{breakFlag = true;});
  for(int i=0;!breakFlag; i++) {
    each(s[i]);
  }
}
So the function passed to forbreak takes an 'escape continuation', so-to-speak, and returns a function to iterate with. Then the iterator function can use the escape continuation to break off the iteration when desired. Foreach can be implemented trivially on top of forbreak:
foreach(c@Collection, func) = c.forbreak(()->void esc=>func);
and it seems like a more generally useful building block for functions on collections which may or may not be sequences, or support size(), or what have you. For instance, find() is currently defined on Sequence, but with forbreak installed, it could be promoted up to Collection. If we added a method mkEmpty, which would produce an empty collection (i.e., much like a no-args constructor) to Container, then we could define foldLeft, map, filter, etc. top of forbreak. So for collections to get all that great functionality, they only have to define mkEmpty and forbreak. Actually, mkEmpty plus either forbreak or fold would do. Maybe we should make fold the base operation, and forbreak can easily be built on that as well.

-- BrynKeller - 05 Aug 2002

And alternate design uses exceptions. You make the iterating function catch an exception called Break. In the anonymous function, it is possible to break by just throwing that exception. One advantage is that we can add that functionality to foreach itself, and clients don't need to do anything if they don't need breaking.

foreach(c@java.util.Collection, f) 
{
  try {
    for (let i = c.iterator(); i.hasNext();)
      f(i.next());
  }
  catch(Break ex) {}
}

Usage:

List<String> l = [ "A", "B", "C" ];
l.foreach(String s => { println(s); if (s.equals("B")) throw new Break(); });

Does someone know (or can make experiments to find out) if the try block would cause a performance penalty, in case the client does not need to break?

Would foreach with Break exception support a good solution? Is forbreak still needed, because it is more general?

-- DanielBonniot - 06 Jun 2003

I think it would be a perfectly acceptable solution. The try/catch overhead probably isn't worth worrying about, since it's only getting set up once. It also has the advantage that if we implement map, filter, foldLeft, etc. in terms of this new foreach, then you can throw new Break() out of any of those as well, which could be handy.

-- BrynKeller - 11 Jun 2003

Unlike foreach, those functions return a value. What would be the semantics of breaking inside those? For instance, what does [1,2,3].foldLeft((int i, int j) => throw new Break(), 0) return? -- DanielBonniot - 11 Jun 2003

Zero, I'd say. Actually, the current definition of foldLeft would already work:

<Any T, Any U> U foldLeft(java.util.List<T> l, (U, T)->U f, U init)
{
  U res = init;
  l.foreach(T elem => { res = f(res, elem); });
  return res;
}

assuming that foreach looks something like this:

<T> foreach(c@java.util.Collection, f) 
{
  try 
    {
      for (java.util.Iterator<T> i = c.iterator(); i.hasNext();)
      f(i.next());
    } 
  catch (Break b)
    {
      //Ignore
    }
}

Oh, it seems everything's already implemented with foreach, so we should be all set:

<C,T,U> map(c, f)
{
  C<U> res = c.similarEmptyCollection();
  c.foreach(T elem => { res.add(f(elem)); });
  return res;
}

<C,T> filter(c, test)
{
  C<T> res = c.similarEmptyCollection();
  c.foreach(T elem => { if(test(elem)) res.add(elem); });
  return res;
}

-- BrynKeller - 11 Jun 2003

That would at least break the implementation of map on arrays (file arrays.nice):

<C,T,U> map(a@Array, f) = fill(new U[a.length], int i => f(a[i]));
If f is allowed to throw Break, then we cannot assume that the result will have the same size as the argument. We could of course adapt the implementation. My question is: is it useful, and clean, to allow to break during map, filter, ...

-- DanielBonniot - 12 Jun 2003

Hmm, that's a good point. I would say it's definitely useful - I seem to recall often wanting to break out of maps and filters in the past. Clean is another question - as you pointed out, handling Break in some cases could make things less efficient - for instance map for arrays would have to be written something like this:

<C,T,U> map(a@Array, f)
{
  List<U> list = new ArrayList(); //or maybe LinkedList
  list.foreach(T elem => { res.add(f(elem)); });  
  return list.toArray();
}

which is clearly going to be slower than the current implementation. Is it worth it? I'm not sure. What if we kept foreach the way it is now, but added forbreak as a foreach where you could throw a Break , and then added new methods like mapbreak, filterbreak and so on? Another approach that would be a little odd but would clutter the namespace less would be to define foreach like this:

<T> foreach(c@java.util.Collection, f, allowBreak = false) 
{
  if (allowBreak)
    try 
      {
        for (java.util.Iterator<T> i = c.iterator(); i.hasNext();)
          f(i.next());
      } 
    catch (Break b)
      {
        //Ignore
      }
  else
    for (java.util.Iterator<T> i = c.iterator(); i.hasNext();)
      f(i.next());
   
}

and then we could write other methods with allowBreak parameters too:

<C,T,U> map(a@Array, f, allowBreak)
{
  if (allowBreak)
    List<U> list = new ArrayList(); //or maybe LinkedList
    list.foreach(T elem => { res.add(f(elem)); }, allowBreak = true);  
    return list.toArray();
  else
    return fill(new U[a.length], int i => f(a[i]));
}
but maybe this is all getting too far-fetched.

-- BrynKeller - 12 Jun 2003

These days, if you want this sort of thing, you just use the generator library in nice.functional. If you want to break out of a map/filter/etc. you just call stop() and that's equivalent to breaking. So:

import nice.functional;

let foo = naturals().filter(
              int i => {if (i == 53) { stop(); } return odd(i);
          ).map(int i => i.toString);

gives you a generator which starts with all the naturals, filtered down to only the odd ones, converted to strings. Except the method passed to filter calls stop() when it hits i == 53, so the whole chain ends at that point. It turned out to be a lot simpler than rewriting the entire collection hierarchy and so on.

-- BrynKeller - 02 Feb 2004

There are still reasons why we would want to modify the collection hierarchy (not necessarily the implementation, but make it have a different hierarchy structure) so that it would have no unsupported operations. That's a different project, of course.

-- DanielBonniot - 03 Feb 2004

 


StandardLibraryMethods  

08 Aug 2003 - 15:47 - r1.3   ArjanB

An overview of the methods and function in stdlib for discussing semactics and as starting point of the documentation. The documentation comments are before the signatures and discussing about sematics and implementation after the signature.

Collection methods

<Any T> void foreach(java.util.Collection<T>, T->void);

<java.util.Collection C, Any T, Any U> C<U> map(C<T>, T->U);

<java.util.Collection C, Any T> C<T> filter(C<T>, T->boolean);
A more precise type for filter would be:
<Collection C, T, U | T <: U> C<U> filter(C<T>, T -> boolean);
This would allow List lA = lB.filter(...) where B is a subclass of A.

/** Return a collection containing all elements for which converter
    returns a non-null value.
    It is possible to retain only elemnts with a subtype of the original
    element type, in which case the returned collection has that 
    element type.
*/
<Collection C, T, U> C<!U> filter(C<T> source, T->?U converter);

/** Modifies c, only keeping the elements for which test returns true. */
<T> void retain (Collection<T> c, T->boolean test);

/** Modifies c, removing the elements for which test returns true. */
<T> void remove (Collection<T> c, T->boolean test);

<Any T, Any U> U foldLeft(java.util.List<T> l, (U, T)->U f, U init);

<Any T, Any U> U foldRight(java.util.List<T> l, (T, U)->U f, U init);

<Any T> List<T> slice(List<T> list, int from = 0, int to = -1);
to is now inclusive maybe exclusive is better.

/**
   comparator must return a negative integer, zero, or a positive integer 
   as the first argument is less than, equal to, or greater than the second.
*/
<T> void sort(List<T> list, (T,T) -> int comparator);

<Any T> boolean contains (java.util.List<T> s, T->boolean test);

/** Find the first element that passes the given test.
    @throw java.util.NoSuchElementException if there is no such element.
*/
<Any T> T find (java.util.List<T> s, T->boolean test);

/** Find the last element that passes the given test.
    @throw java.util.NoSuchElementException if there is no such element.
*/
<Any T> T findLast (java.util.List<T> s, T->boolean test);

/** Find the first element that passes the given test.
    Returns <code>null</code> if there is no such element.
*/
<Any T> ?T search (java.util.List<!T> s, !T->boolean test);

/** Find the last element that passes the given test.
    Returns <code>null</code> if there is no such element.
*/
<Any T> ?T searchLast (java.util.List<!T> s, !T->boolean test);

<Any T> int indexOf (List<T> s, T->boolean test);

boolean or(java.util.List<boolean> s);
shouldn't this be defined for Collection
long max(java.util.List<long> s) requires !s.isEmpty();
shouldn't this be defined for Collection

/** @return the concatenation of the two lists, as a new list. */
<T, T1, T2 | T1 <: T, T2 <: T> List<T> `+`(List<T1> l1, List<T2> l2);

Array methods

<Any T> !T[] elementsNotNull(?T[] arr);

/** Returns an array with the newSize first elements. 
    The result can be the same array as the argument.
*/
<Any T> T[] resize(T[], int newSize);

<T,U | T <: U> void copy(T[] from, int fromIndex = 0, U[] to, int toIndex = 0, int count); 

<T,U | T <: U> void copy(List<T> from, int fromIndex = 0, U[] to, int toIndex = 0, int count);

<T, U | U <: T> T[] copy(U[] array);

<Any T> T[] slice(T[] array, int from = 0, int to = -1);
to is now inclusive maybe exclusive is better
/**
   Fills a newly created array with non-null values.

   A typical usage is to allocate a new array and set its values at the same time:
   <code>
     String[] numbers = fill(new String[10], int i => "number " + i);
   </code>

   The equivalent code in Java would be:
   <code>
     String[] numbers = new String[10];
     for (int i = 0; i < 10; i++) {
       numbers[i] = "number " + i;
     }
   </code>

   It is important that no reference to the array is kept,
   because that would make it possible to store null values in it.
   There is no danger as long as the array is created inside the call, 
   like in the above example.
*/
<Any T, Any U | U <: T> U[] fill(T[] array, int->U value);
In particular, this is useful with T = ?X and U = !X. The above type is more general, and useful when the component type is a type variable.

/** Returns an array containing, in order, the elements of both arguments.

    The type of the elements of the arguments can be subtypes of the result 
    elements, since a new array is created.
*/
<T, T1, T2 | T1 <: T, T2 <: T> T[] concat(T1[] a1, T2[] a2);

<T, T1, T2 | T1 <: T, T2 <: T>  T[] `+`(T1[] a1, T2[] a2);

Other methods

<Any T> !T notNull(?T value);

/* 
   Allows to consider any nice object as an instance of java.lang.Object
*/
<Any T> Object object(T);

/** Unsafe cast operator. UNSAFE! */
<Any T, Any U> U cast(T) = inline nice.lang.inline.Nop();

String replace(String source, char c, String with);

String deleteAtEnd(String source, String what);

/**
 * Break a string into a <code>List<String></code> of substrings,
 * splitting at (and removing) every occurrence of the <code>separator</code>
 * string.
 * 
 * @param str the string to split
 * @param separator the separator to split on 
 */ 
List<String> split(String str, String separator)
  requires separator.length() > 0 : "separator cannot be the empty string";

/**
 * Join a collection of strings together, interspersing <code>separator</code>
 * among them.
 *
 * @param strings the strings to join
 * @param separator the separator string to place between each 
 *    string and the one before it
 */
String join(Collection<String> strings, String separator);

Classes

Proposals

/**
  Count the number of elements for which test returns true
*/
<T> int count (Collection<T>, T->boolean test);

/**
  @return true if all boolean in the list are true otherwise returns false
*/
boolean and (List<boolean>);

/**
  @return true if the test returns true for all elements in the Collection otherwise return false
*/
<T> boolean all (Collection<T>, T->boolean test);

<T> T max(Collection<T> coll (T,T)->int comparator) requires !coll.isEmpty()

<T> T min(Collection<T> coll (T,T)->int comparator) requires !coll.isEmpty()

/**
  Fold left without init value
*/
<T> T foldl(List<T> list, (T, T)->T func) requires !list.isEmpty();

/**
  Fold right without init value
*/
<T> T foldr(List<T> list, (T, T)->T func) requires !list.isEmpty();

-- ArjanB - 08 Aug 2003

 


StreamTypes  

23 Apr 2004 - 04:42 - r1.3   RohanHart

Erik Meijer and Wolfram Schulte have some interesting ideas about "stream types" which look like they could improve some of the code I've been writing. See Unifying Tables, Objects, and Documents. Since we already have the stream-like types T and ?T (which correspond to T! and T? in that paper) would it be possible to extend MLsub to provide T* and T+ types?

-- RohanHart - 21 Apr 2004

Good question, I'd be interested in that too.

-- BrynKeller - 22 Apr 2004

 


SuperCall  

11 Apr 2003 - 22:01 - r1.3   DanielBonniot

This page documents the current super mechanism in Nice. It compares it with super in Java, and calls for discussion on ehancements. First, it does not make sense to just copy Java's semantics. In Java you write:

class B extends A
{
  void m(int x) { super.m(x); ... }
}
So super in Java means roughly "fetch the following method in my superclass". With multi-methods this does not make sense, since methods consider all arguments to choose the implementation, not just the first one.

Another odity with Java is that you call call a different method than the current one, or pass it other arguments than the arguments of the current method. I think at least that calling the same method with the same arguments is by far the most common, so it should be more natural to do it, without having to reapeat the method name and arguments.

So the current definition in Nice is that super is an expression that calls the next implementation of the current method, with the same arguments. So the example would become:

class B extends A
{
  m(x) { super; ... }
}

I would be interested to hear if other cases are useful in practice (calling a different method, or passing different arguments). These pose more theoretical problems. For instance the Dylan language says that passing different arguments is fine as long as they will result in the same implementation to be chosen, otherwise the result is undefined.

-- DanielBonniot - 12 Jul 2002

I have used super with different arguments in the case of constructors in Java. They are used to set default or constant values for the base class.

Could you give a price example?

-- ArthurSmyles - 10 Apr 2003

 


SyntanticClassHierarchy  

18 Nov 2004 - 00:21 - r1.3   LucPerrin

In an attempt to understand better the syntax part of nice, here is the class hierarchy for the bossa.syntax package. I have included questions and comments for discussion.

abstract public class Node;

public static class ClassDefinition?.ClassImplementation; Why are these not Definitions? Also, use of inner classes needs to be broken. Definitions are toplevel and ClassImplementation? is just a part of ClassDefinition?.

class Expression;

class AtomicConstraint?;

abstract class Statement;

abstract class Monotype;

abstract class Pattern;

abstract class NiceField?; Why aren't fields Definitions? they are a part of NiceClass?

class VarScope?;

interface TypeMap?;

// Misceallaneous

class Arguments;

class Contract;

class LocatedString?;

final class ValueOverride?;

class ACatch; Why is this not a statement? It's a helper class for TryStmt? because a try can have multiple catches.

// Helpers:

class JavaClasses?

final class NiceUtils?;

final class TypeConstructors?;

class TypeParameters?;

class Info (analyse.nice)

// Other

interface Macro extends gnu.expr.Inlineable

interface Module extends mlsub.compilation.Module

interface Function;

// Exceptions

class DuplicateIdentEx? extends Exception;

class UnknownIdentException? extends bossa.util.UserError;

-- LucPerrin - 17 Nov 2004

 


SyntaxChanges  

14 Feb 2004 - 22:50 - r1.2   BrianSmith

A few syntax changes are being considered now.

-- ArjanB - 03 Feb 2004

 


TestMachine  

22 Jun 2003 - 10:03 - r1.5   DanielBonniot

A TestMachine is a machine that runs the AutomatedTests for Nice. This page documents how to set up a new TestMachine.

Requirements

To be most useful, the tests should be done very frequently. The best is thus to have use a machine that is turned on permanently, and connected to the network. That way, you can configure it to run the tests, for instance, every day at a certain time. Everyting will happen automatically. It's also possible to install the test scipts on machine that are not turned on all the times. The tests can then either be run automatically when the machine is on (using for instance anancron), or manually, at special times, like shortly before a release.

To be able to send the results to the result page, you will need to have the rights to scp a file to the Nice project on sourceforge. As far as I know, this means being a member of the project. If you wish to set up a TestMachine, but are not a member of the project, contact DanielBonniot.

Setting up the tests

Download

First, you need to download from CVS the test scripts. Choose the directory to install the scripts in, and move into it before.

cvs -z3 -d:pserver:anonymous@cvs.sourceforge.net:/cvsroot/nice co tester

Configure

You need to configure two files:

The following variables are needed by the script. They all get default values.
Variable Meaning Default value
user Your user name on sourceforge $USER (your user name on the local machine)
machine A name identifying this machine hostname -f

If you need to override them, you must create a file called setup in the main directory. For instance, since my user name at home is daniel, I have a setup file with one line:

user="bonniot"

This is the file that decides what versions of tools are used to run the tests. It is possible to have several, in which case the tests will be run several times. name will be used to identify each configuration. Choose it to reflect the main points of that configuration. At the moment you only need to configure JAVA_HOME.

For instance, I have a file config.jdk1.4 that contains the following line:

JAVA_HOME=/usr/local/opt/j2sdk1.4.1

Check

Let's check that your installation is correct. From the main directory, type:

./run

The scripts will download the latest version of Nice, and of several applications. Then it will try to bootstrap the compiler, and to use it to compile the applications.

If all goes well, you will have in the builds subdirectory the results of the testing, in the *.res files, and the logs of the build for each configuration in the *.log files. The script has also attempted to send them to sourceforge, where they will be processed to be included in the result page. That page is generated once every hour.

If there seems to be a setup problem, look at the builds/*.log files to see what happened.

Automatise

This depend on your system. On unix, you can use crontab to configure when the tests should be run. I use the following contab entry:

20 13 * * *   (cd $HOME/OSS/tester; nice ./run)
Note that nice is used to give the build a low priority, so that it does not slow down my machine. It has nothing to do with Nice!

-- DanielBonniot - 26 Apr 2003

 


TestSuite  

02 Aug 2003 - 15:40 - r1.5   DanielBonniot

This page documents the testsuite engine for Nice. It also contains a list of wanted features that are not implemented yet.

Nice TestSuite Documentation

The Nice TestSuite is a framework to test the Nice compiler. For this aim, a proprietary file format for the testcases has been created. Here are some testcase examples:

/// COMMENT This testsuite tests the following ....
/// PASS
  int a = 1;

/// PASS
  /// TOPLEVEL
  /* A simple global var. */
  var int x = 0;


/// FAIL
  /// COMMENT this should fail
  int a = "";

/// PASS
  /// package a
  /// TOPLEVEL
  class A
  {
    int x = f();
  }
  int f() = 0;
  /// package b import a
  ;
TestCase? keywords are all prefixed with ///. On root level (without any whitespace indentation) currently following keywords are allowed

PASS and FAIL

The keywords PASS and FAIL indicate a testcase on its own, and whether the expected behaviour while compilation is pass or fail. Testcases cannot reference each other, they are all compiled and tested independently.

Known bugs

When a bug is found, I often write a testcase for it first, before the bug is fixed. In that case, it is useful to flag the testcase as being a known bug. This is done by adding bug at the end of the line. I such a testcase is indeed found to include an error, well we knew it and print nothing. But if it works, then print a victorious message! :-). In the summary:
  known bugs: 2
  fixed: 1

Testcases may contain the TOPLEVEL keyword that has the following meaning: everything in front of the TOPLEVEL keyword will be collected in the main() method. Statements behind the TOPLEVEL keyword are global to the package, like global variables, functions, methods and class definitions.

PACKAGE The PACKAGE keyword indicates which package the sources should belong to. More than one PACKAGE keyword can be declared to build a testcase with a certain package structure. Packages can be imported by the PACKAGE some IMPORT other keywords.

Global

After the GLOBAL keyword source code can be written that is accessable by all following testcases. Global sources can be placed at where (before, after or between testcases) in the testsuite file. The scope of global sources is restricted to the same testsuite file and to testcases that are behind the global source. Globals can appear more than one times in the file as the next example demonstrates
/// GLOBAL
  int g1 = 1
   
/// PASS
  /* access to g1 only */
  int a = 1;

/// GLOBAL
  int g2 = 2

/// PASS
  /* access to g1 and g2 */
  /// TOPLEVEL
  /* A simple global var. */
  var int x = 0;
Because globals are accessible only in the same file, placing global sources at the end of the file makes no sense.

Comments

Comments can be included, and if desired outputted, at any place in a testsuite. Comments have the following syntax /// COMMENT place your comments here

Comments are one-liners, if you want to write a long comment, write the whole comment in one line as described above or break it into more COMMENT keywords, each in a new line. The following example shows possible ways to comment

/// COMMENT This testsuite describes ....
/// GLOBAL
    ...
    
/// PASS
    /// COMMENT This testcase demonstartes ...
    /// COMMENT ... line two of testcase comment ...
    ...
    
/// COMMENT here we could comment the end of the testsuite :)
Activating comments in the output can be done by specifying the -comment flag in the command line

java -classpath /usr/share/java/nice.jar nice.tools.testsuite.TestNice ~/testsuite/ -comment or java -classpath /usr/share/java/nice.jar nice.tools.testsuite.TestNice -comment ~/testsuite/

While running the testcases temporary files and folders are created in "testsuite-temp-folder". Testcases that fail, in the sense of that they don't behave like expected (pass or fail) are collected in the folder "testsuite-fail-folder" for later investigation purposes. In this folder, each testcase is grouped in its own folder that is numbered from "1" on in ascending order. At the next testsuite run both folders are initially cleared. -- AlexGreif? - 27 Jun 2002

Specifying the location of failures

In a /// FAIL test, it is often desirable to specify where (which line, which column) the error should be reported. This allows for checking that the compiler gives the good location to the user, and also that the test does not fail "by accident", for an other unrelated reason (for instance a syntax error when writing the test).

This can be done, by embedding a comment of the form /* /// FAIL HERE */ just before the location of the desired error in the test source.

Warnings that result from wrong FAIL HERE positions are treated sort of failures. Thus the source code is shown and the compiler results.

Running the testsuite

To run the whole testsuite, just call make check in the main directory of Nice.

To run a specific subset, you can use:

java -Dassertions=true -classpath classes nice.tools.testsuite.TestNice testsuite/<directory>

If you use Java 1.4 or later, use java -ea instead of java -Dassertions=true (this should also be done in the Makefile, but how do we make it work for both 1.3 and 1.4?).

Feature requests

Saving output for failed tests

When a test fails, it would be useful if the output of the compilation (and the output of the run, with the stack trace of the exception thrown) was saved in a file, in the failure directory.

Saving successful tests

Sometimes I want to look at the code generated by succesful tests. It would be good to have a -save comment line option to say to save all tests, not just the failing ones.

Well, that's all for now! Quite a lot of new features :-) None is critical, so do what you can when you find the time. But all these features will make testing easier.

Compiler warnings

We need to track compiler warning, not just errors. I think by default a warning should be considered as an error. We could add a ///WARN tag to say that a test should (or can?) emit a warning. (Not urgent: I'm not sure if there is any interesting warning issued by the current compiler).

Failure positions

At the moment, the testsuite engine emits a warning if there was no error where you expected one. It should also warn if there was an error where you did not expect any. Probably, as an exception, a test case that has no explicit FAIL HERE is also OK.

The rationale is to test cases, like the one I just solved, where one error is expected, but the compiler reports two errors.

Macros

It could be useful to define some macros, in the form of /// keywords, for tests that are repeated many times with a similar pattern.

One example is:

/// TYPE Type1 SUBTYPE OF Type2

In the engine, this would be expanded to some Nice source that will compile if and only if Type1 is a subtype of Type2.

This is not urgent. If we really need something like this, perhaps it would be wiser (and more fun!) to transition the testsuite to a set of Nice functions, so that test cases could be written in Nice itself.

 


TodoList  

18 Oct 2003 - 15:04 - r1.6   ArjanB

Overview of the things left to do in random order

-- ArjanB - 08 Aug 2003

 


ToolsAndLibraries  

03 Dec 2004 - 17:56 - r1.10   MartinGamsjaeger

Current projects

Future projects (waiting for volunteers)

 


TreeDataConstruction  

03 Jan 2005 - 00:09 - r1.6   MarkCC

An interresting idea from the Groovy language is to have an easy way to create tree like data as xml, html and user interfaces.

More info: http://groovy.codehaus.org/markup.html

-- ArjanB - 08 Jan 2004

Erik Meijer using declaritive XML markup for GUIs inside a program and using declaritive XML markup for arbitrary types

public class Contact {
  sequence {
    string Name;
    string? Email;
  }
}

public class Test {
  static void Main() {
    Contacts cs = <Contacts> 
                    <Contact>
                      <Name>Erik Meijer</Name>
                      <Email>{"emeijer"
                              +"@"+
                             "microsoft.com"}
                      </Email>
                    </Contact>
                    <Contact>
                      <Name>Dare Obasanjo</Name>
                    </Contact>
                  </Contacts>;
...
  }
}
-- IsaacGouy - 09 Jan 2004

I like the idea of a language that understands xml and can express and check types for it. But imho xml literals are just ugly. Humans should not have to grok XML

Though most things(like gui's) could be written in some xml format, it's better to have some syntax that's more general and easier to read.

-- ArjanB - 09 Jan 2004

Never wanted to read much XML myself. OTOH when I read about Groovy support for various markup languages from XML, HTML it seems reasonable to represent snippets of XML by... well, snippets of XML. That seems more obvious and more general. -- IsaacGouy - 10 Jan 2004

Speaking from experience from working with Groovy, Groovy markup is absolutely wonderful for some things, But sometimes, it's even more awkward to write XML tree constructors in function-invocation syntax than in XML syntax. It can be very annoying. Using XML in-place can be terrific - for a great example, see Scala.

-- MarkCC - 03 Jan 2005

 


TupleFunctionDeclaration  

18 Jun 2003 - 18:07 - r1.3   DanielBonniot

This page describes the feature request to use tuple types in function declarations and anonymous functions.

The following code shows the currently working way. The new feature is commented out.

package test;
import java.util.*;
void main(String[] args) {
  List<(String, String)> tuples = new ArrayList();

  tuples.add(("a", "1"));
  tuples.add(("b", "2"));

  //   works fine
  tuples.foreach((String, String) tuple => {
      (String letter, String number) = tuple;
      println("letter: "+letter+" number: "+number);
    }
  );

  /*
  //   does not compile
  tuples.foreach(((String letter, String number)) =>
    println("letter: "+letter+" number: "+number)
  );
  */
}
-- AlexGreif? - 05 Mar 2003

I agree it would be practical to be able to name the components of the tuple in its type declaration. This is actually already possible for a local declaration, which you use in the first function. But it needs to be implemented for function declarations.

We also have to disambiguate with the first case, by putting additional brackets:

((String letter, String number)) => ...

-- DanielBonniot?

This feature is now implemented (in the CVS-tree and will be in the 0.9.0 release) -- ArjanB - 16 Jun 2003

 


TypeAlias  

04 Jan 2004 - 22:04 - r1.4   ArjanB

Arjan has mentioned this a couple of times.

Given that Nice is more than an OO language, do we need more than the ability to define a new object?

(On a related subject, maybe it's worth (no pun intended) mentioning that subrange types were removed from Modula-2 in the transition to Oberon-2, too complicated with too little benefit. Probably worth considering subranges separately.) see also CheckedIntegerArithmetic

-- IsaacGouy - 31 Dec 2003

The purpose of a TypeAlias is improve readability by being able to replace long types which are used in multiple places in the source code. Making a subclass or interface is not always possible because that can have semantic side-effects.

Thingy = Map<Foo<Bar>, List<String>>
MyFunction = (List<Foo>, Bar, int, String)->int
Another advantage is that TypeAlias could make explorative programming easier. When you don't know yet which type to use, you can use a TypeAlias so that changing the type don't require that much changes all over the place anymore.

-- ArjanB - 01 Jan 2004

And 'Thingy' & 'MyFunction' showing up in error messages?

-- IsaacGouy - 03 Jan 2004

Preferably but it will be quite hard to implement -- ArjanB - 04 Jan 2004

 


TypeErasureLimitations  

30 Apr 2005 - 12:14 - NEW   TWikiGuest

Generics are implemented in Nice using a technique called `type erasure' - just like in Java 5.

The technique and some of its repercussions are quite nicely described at: http://gafter.blogspot.com/2004/09/puzzling-through-erasure-answer.html

Basically, choosing for type erasure means the knowledge which type parameter was used is known at compile-time, but not anymore at runtime. That is why you can do `foo instanceof NiceVector?', but not `foo instanceof NiceVector?<String>'.

Also, casting a NiceVector?<Integer> to NiceVector?<String> will not give a ClassCastException?. This means you can add strings to a (casted) NiceVector?<Integer>, and you'll find out only when you try to remove that element from the NiceVector?<Integer> as an Integer. In other words, you'll get a ClassCastException? in another place then where the bug is, and in fact in a piece of the code where there is no cast.

-- Main.Raboof - 30 Apr 2005

 


UnknownType  

12 Nov 2003 - 14:01 - r1.4   DanielBonniot

Unknown Type

I'd like to propose something that, at first glance, goes against the strongly typed phylosophy of Nice and Java. I'd like to have the ability to sometimes have a variable that does not have a known type, at compile time. This would mean that the compiler should make no assumptions on the variable's type. It would also mean that these variables would have to be resolved at runtime, for access to their fields and methods.

In Java or Nice today, we are forced to get by using an Object type, when we don't or can't know the type. The main problem with using Object is all of the type casting and instanceof operators that must be used with these variables or members.

Since Nice has MultiMethods?, meaning that methods are found dynamically, it only seem logical that this also be possible to accomplish at runtime, rather than compile time.

Syntax

We would add unknown (and ?unknown) as a primitive (built-in) type. Here are some examples of the use of unknown:

    unknown depthSearch(Tree tree, unknown find);

    unknown entry = "This is a string";
    ?unknown first = null;
    unknown[] list1 = new unknown[50];
    var list2 = new ArrayList<unknown>();

    int len = entry.length();       // works because entry currently refers to a String and because
                                    //   String.length() returns an int
    file = new File(entry);         // works because File has a Sring constructor, and without typecasting
    int width = entry.width();      // would compile, but fail at runtime
    Set<int> set = entry.charAt(0); // seems silly, but would compile, then fail at runtime

Pros

Most scripting languages like Perl, Python, Ruby, and JavaScript never declare types for variables. Here are some of the advantages of unknown variables.

Cons

There are some problems with untyped variables, which is why many of us favor strongly typed languages for enterprise level projects. Because of these problems, the use of untyped variables should not be easy or encouraged, as they are in scripting languages. Here are a few of the problems.
    unknown found = list2[15];
    if (found instanceof Number) {
        /* Compiler knows 'found' is a Number here and can take advantage of that */
    }

See also DynamicMembers for an idea of how to possibly implement runtime member lookup.

-- TroyHeninger - 25 Oct 2003

Thanks for your ideas. It is true that although strong typing is better when it is possible (and with Nice we try to make it possible more often), there will always be cases where it is not "clever" enough.

One aspect of Nice you might have missed is that, with type parameters, you can handle some of the situations you mention. For instance, instead of

  unknown `.`(row@Results, String column);
you can already write:

  <T> T `.`(row@Results, String column);

which says: the return type is T, for whatever value of T you choose (since T does not appear in the parameter list). This is already used in the standard library for serialization/deserialization without casts. You can also look at this forum thread about reflexion support.

This does not allow to have a local variable of any type, though, because T must be declared in a method type. But I believe this already covers many interesting cases.

-- DanielBonniot - 25 Oct 2003


That brings up several questions. 1) Does Nice currently support overriding the `.` operator, as you implied above? If so, then you've already answered my request for this in DynamicMembers. 2) With Nice's current type capabilities, is it possible to create an array or tuple of unknown types? I don't think it is. 3) How hard would it really be to add unknown to Nice? If you don't think it would be too hard, I'd be willing to look into adding it myself. I do have compiler writing experience, though I don't have tons of time.

-- TroyHeninger - 12 Nov 2003

1) You can put anything inside ``, so a method definition using `.` is valid. However, you would not be able to call it using the e1.e2 syntax, so that's not yet what you want (in the other discussion). My point here was about typing.

2) You're right, using <T> for unknown types does not carry on to arrays. What you can do currently is use Object for that purpose. You can convert any value to Object by using the method object(...). On the way back, you would use a cast or instanceof.

3) Basic support exists, using Object as described above. One could do better, by not requiring the use of object(...) (that is, make Object the top type). This should not be very difficult.

If you want to allow any operation on Object (or unknown) to succeed, and discover the operation at runtime, that would more work. Although maybe you could just rewrite f(e1, ..., eN) where at least one of e1...eN has the unknown type into dynamic_call("f", e1, ..., eN), and implement dynamic_call as a library function that uses reflexion and the class of its arguments to find what method to call. Is this what you are driving to?

It's interesting, although my bias is usually more towards static solutions. I'm not sure if you are awre that Nice is already quite clever about instanceof, so you don't need casts in addition:

Object f = operationReturningAnything();
if (f instanceof String) {
  // f has type String here, no cast required.
  int len = f.length(); // String operation, resolved at compile time.
}

This removes about half of the boilerplate needed in Java when using arbitrary types. If the removal of object(...) mentioned above was implemented, would not this provide quite a good support already, without loosing any type safety?

-- DanielBonniot

 


UserManualOmissions  

07 Jul 2005 - 10:05 - r1.43   DanielBonniot

These are aspects of the language that are not covered by the User Manual, but that should be.

Aspects that should be updated:

Things that we can't do yet:

Things that have now been done:

Discussion


The documentation for || with nulls should explain the interaction between || and autoboxing. In particular, 1 || 2 seems to be the same as new Integer(1) || new Integer(2). (The compiler should also be able to detected the dead code in this situation: new Integer(1) can never be null, so new Integer(2) is never executed.) Also, the documentation should explain the way that || coexists with the nullness checking for fields as demonstrated at the end of this example:

    class A { ?Integer n; }

    void main(String [] args) {
        println(0 || 1);
        println(2 || 1);


        println(null           || new Integer(1));
        println(new Integer(2) || new Integer(1));

        let a1 = new A(n: null),
            a2 = new A(n: new Integer(2));

        println(a1.n || new Integer(1));
        println(a2.n || new Integer(1));

        Integer n1 = a2.n || new Integer(1);
        println(n1);

        // NOT equivalent to
        //    n2 = a2.n || new Integer(1);
        // error:
        //    The value if(`!=`(a2.n(), null))
        //                 a2.n()
        //              else
        //                 new Integer(1)
        //    cannot be assigned to n2 because it might be null.
        //
        // Integer n2 = a2.n != null ? a2.n : new Integer(1);
        // println(n2);

        // equivalent to
        //    n3 = a2.n || new Integer(1);
        ?Integer temp = a2.n;
        Integer n3 = temp != null ? temp : new Integer(1);

        println(n3);
    }
Output:
    0
    2
    1
    2
    1
    2
    2
    2


Why do you use Integer as type instead of int? What made you trying out all kinds of variations with the || operator?

I don't think users need to know about how autoboxing happens. -- ArjanB - 29 Jan 2004

It was mentioned in the ConstructorSyntax discussion I believe. I tried it out because it wasn't documented and I wanted to figure out the semantics. I think it is important to document the semantics explicitly. But I think that I may be wrong about autoboxing anyway; it is also not documented and I haven't been able to figure out the autoboxing semantics yet. Anyway, I think that operator || is simply mistyped and should not apply to int/byte/long/float/double since it doesn't make any sense for numeric types. Maybe the typing should be:

    <Any T, T U> !T `||`(#?T e1, !U e2) = inline nice.lang.inline.OptionOr();
    <Any T, T U> ?T `||`(#?T e1, ?U e2) = inline nice.lang.inline.OptionOr();
That is, somehow require that the first parameter be an option (nullable) type. The Nicec compiler doesn't accept this syntax but maybe there is another way? -- BrianSmith - 29 Jan 2004

The OptionOr? can make sense for numeric types too, example:

Map<String, int> map = new HashMap();
map["abc"] = 5;
int n1 = map["xyz"] || -1;
int n2 = map["abc"] || -1;
println(n1); //prints -1
println(n2); //prints 5

It's not possible to give OptionOr? a type so that it requires the first parameter to be an option type because of the typechecking rules for function application. But OptionOr? is an inlined operator so it would be possible to generate a warning when using it with a non option type first argument.

-- ArjanB - 29 Jan 2004

|| is a method defined in nice.lang, so I don't think it should be documented in the UserManual?. As soon as we have a working nicedoc, we'll publish the documentation for the standard libraries on the website.

The general question is to document when autoboxing happens. On the one hand, one can often see that as an implementation detail, but either when you use reference equality or for performance reasons, it is sometimes important to know. So yes, that should be better documented. I'm not sure if it should go in the UserManual?, or if we should have a different document for lower-level aspects like this (this does not really belong to the definition of Nice itself, it just happens to work like this when you compile to the JVM).

The rule is that when a primitive value is used when a generic type (T) or an Object is expected, the value is boxed. Unboxing happens as need when a boxed value is used where a primitive type is expected.

-- DanielBonniot - 30 Jan 2004

String Examples

The documentation mentions multi-line strings but it would be clearer to show how they would map to traditional syntax. For example, it is not clear how whitespace at the beginnning/end of an internal line works in a multi-line string.

    let greeting  = """
            Hello, world.
       You may be thinking, \"Why was I called here today?\"
       Well, there was a good reason. Honest.
      """;   
Is it equivalent to:
   let greeting  =   "Hello, world. "
                 + "You may be thinking, \"Why was I called here today?\" "
                 + "Well, there was a good reason. Honest.";
or:
   let greeting  =   "Hello, world.\n"
                 + "You may be thinking, \"Why was I called here today?\"\n"
                 + "Well, there was a good reason. Honest.";
or something else?

Hmmm maybe there's something to be said for being explicit, my guess would have been

   let greeting  =   "\nHello, world.\n"
                 + "You may be thinking, \"Why was I called here today?\"\n"
                 + "Well, there was a good reason. Honest.\n";
-- IsaacGouy - 08 Feb 2004

 


VisibilityModifiers  

12 Jan 2005 - 03:16 - r1.15   RohanHart

What should be the exact semantics of the VisibilityModifiers?

Can VisibilityModifiers added to method declarations or method implementations or both?

How do VisibilityModifiers affect where you can implement and/or call methods?

I have thought about this but I didn't get consistent and usefull semantics. The only easy ones are the global constants.

Anyone some good ideas?

-- ArjanB - 09 May 2003

It's also easy for functions (unless we have FunctionsReplacedByMultiMethods, in which case the question disappears).

For methods, I think that visibility only makes sense to method declaration. It should restrict the places from where you can call the method. I don't think that we can/should restrict the places you can implement the method, because I believe that in some situations you would need to implement a method where it is not accessible.

Similarly for classes, visibility should not restrict implementing a method for that class. I can see two usages for non-public classes. One is to make the constructor restricted, which means you cannot instanciate them outside the scope. The other is that you cannot use them in types. The first one is surely needed (singleton pattern). I'm not sure about the second. A possibility is that both would be restricted. I think the second one is too restrictive to be useful in practise.

- DanielBonniot - 10 May 2003

The simplest solution is to make VisibilityModifiers only affect the places where you can call a method/constructor. I think there should also be a way to restrict the places where you can implement a method. Implementing a simple form of the VisibilityModifiers first and using them will give more insight in what kind of additional restrictions are needed.

-- ArjanB - 03 Jun 2003

Agreed. I thought that a good way to start implementing this would be to develop an independant library for managing symbols with visibility properties. That would help keeping the complexity out of the compiler, and thinking abstractly. It should probably be implemented in Nice, but keep in mind might be called by some Java code. Anybody feels like working on this?

One feature that I find useful is when "invisible" symbols are not completely ignored, but the system can tell you "foo is defined in package bar, but it is not public". Something to keep in mind is that we might want to have different visibility for the same symbol in different contexts (ex: a field that is public when reading it, but private when writing it). That could come in a second phase, though.

-- DanielBonniot - 04 Jun 2003


In InnerClasses, I mentioned that I use inner classes in Java to emulate Eiffel's selective export language feature. ArjanB? mentioned a "proposal is to give sourcefile access to things with the private modifier." I'm not sure how this works with methods of a class being defined in multiple files, multiple classes methods' being defined in one file, etc., so some of my concerns below may be irrelevent.

I think making all the classes in a single source file the equivalent of friends would be a mistake. It removes nearly all the benefit of visibility modifiers for classes inside one source file, which would end up encouraging a more Java-like one class per file. It makes the most common case difficult in favour of making the less common easy (if not too easy.)

It would also be far coarser grained than an Eiffel-like selective export, becoming all-or-nothing. You could not restrict access to a subset of methods, but would have to either give access to everything or everyone access. For example, you want to give class B access to method Z of class A. To achieve this with the friend-like proposal, you either give class B access to everything of class A, or give all classes access to method Z. Neither choice is ideal. With selective export, you could just list class B in the export list for method Z, instead of specifying public or private.

Further, it makes specialization difficult. By specifically restricting to classes within the same source file it prevents subclasses defined elsewhere (which is how package, friend, and inner-classes work, I don't know about the Nice proposal) from achieving the same degree of flexibility. With selective export, you could create a class C subclassed from class B, and it would still have access to method Z. With package/friend/inner classes, you'd have to actually define class C in the same source file as class B, which is impractical and often impossible (e.g., class B is in a library.)

Selective export is a wonderfully usefull feature, but is all about finesse and fine control. Emulating it with package/friend/etc. is destructive overkill. I'd love to see Nice gain this advantage over Java. I'm not sure how they would interact with multi-methods though.

I must also say that I find it a little unsettling that units of storage, the source file, are being given semantic meaning in the language. While certainly convenient to the language designer, I think it makes the language a bit inflexible.

-- Vulcannis - 28 Aug 2003

The main problem of visibility in nice are multimethods, they do not belong to a class so defining usefull semantics is difficult. I haven't seen any other language with multimethods that has visibility restriction. For acces related to subclasses as protected in java I see no way to give them clean semantics. Besides restricting where a method can be called we need a way to restrict where method implementations can be added. Visibility remains an open issue for now, probably it will be implemented in many small steps to find out a good balance between control and flexibility. I will take a look at eiffel for hopefully some good ideas.

-- ArjanB - 28 Aug 2003


I'm going to consider only class or package member (field and method) access from functionals (multimethods or functions) and ignore class visibility. Here's a diagram of Java's visibility rules for accessing. At each functional implementation location relative to the member we're accessing, all members with any visibility below, to the right, equal to the table position are accessible:

Location same class subtype of class anywhere
same file private    
same package     (package)
anywhere   protected public

From the above we get two chains of inclusion: public > package > private, and public > protected > private, where > means “is more accessible than.” It's possible to apply the exact same visibility rules to Nice. Using these rules would be a good place to start.

The rules for accessing private members could be relaxed. Private members could be permitted to be accessed by any functional, as long as they appear in the same file. Since Nice functionals aren't very strongly linked to classes, I favor this approach. The table is displayed below. At each location relative to the member we're accessing, all members with any visibility below, to the right, equal to to the table position are accessible:

Location same class subtype of class anywhere
same file     private/protected
same package     (package)
anywhere   protected public

Discarding protected would simplify the above table: private would mean “this file only,” and package and public are self-evident (protected is not currently even a recognized keyword in 0.9.1). However some design patterns, e.g. Template Method, rely on protected. I think protected can be implemented for multimethods: a given method implentation should have access to protected members of any objects that are passed to it via dispatch.

It should definitely be possible to specify different visibilities for reading and writing fields. Trouble is, there are a lot of combinations of visibility, even with the restriction that field set must be less visible than field get. Something like public(read) private(write) int x; or public(get) private(set) float y are very clear, but verbose. Hyphenated words might work: public-private, public-read (package write), and private-write (package read) cover all the cases that don't involve protected.

A side note: it's also possible to provide support for rare cases where accessing a hidden member may be desirable. AspectJ provides the privileged keyword for this (http://dev.eclipse.org/viewcvs/indextech.cgi/~checkout~/aspectj-home/doc/progguide/apbs05.html#d0e6222). It applies to an entire aspect, and grants that aspect the ability access to all members. If privileged is deemed useful for inclusion in Nice, I think it should apply at the functional implementation point instead of the class level, but the idea is still the same.

-- JohnBMesserly - 29 Aug 2003

Nice seems to have more than the usual design constraints, because of the expectation that Java classes will be extensively reused in Nice code. In the MethcallIntermediateExample, the java class in JavaToggleExample was written with the expectation that subclasses could access protected fields - that is not the case in Nice 0.9.2

The handling of protected java fields/methods is a known problem that needs to be fixed. -- ArjanB

-- IsaacGouy - 17 Sep 2003

I agree with Daniel that for methods, visibility only makes sense for the method declarations and should affect (only) the places you can call the method. But, I agree with Arjan that there should be a way to prevent specializations of a method from outside the package it is defined in.

It makes sense that a class's visibility would affect the ability to implement a method for that class. For example, if a class C is private to a package a.b.c, it should not be possible to define a multimethod that has an a.b.c.C argument or return type outside of package a.b.c. Similarly, it should not be possible to define a public method M in package a.b.c that is declared to accept parameters of type a.b.c.X or returns type a.b.c.X.

The visibility of a class's constructor should be at least as restrictive as the class's visibility. For example, it doesn't make sense to have a public constructor for a package-private class. However, it does make sense to have a package-private constructor for a public class. It might be useful to have protected for constructors--A protected constructor of class X can only be used by a constructor for a subclass of X. Then you could also have package protected which would allow use of the constructor by a subclass of X as well as by any code defined in the same package as X.

Beyond constructors, I don't think any modifier giving subclasses special privileges is very useful. Presumably, it would only apply to the classes' initializer and the default value expression for its fields.

I agree with Vulcannis when he says that it is "unsettling that units of storage, the source file, are being given semantic meaning in the language." But at the same time it does seem useful to have source-file level visibility as long as a single package can be spread across multiple source files. Perhaps a good way of handling this would be to have a package visibility modifier instead of private. A symbol (class, method, field, value) without a visibility modifier would be visibile only within the source file it is declared in. To grant access to other source files in the package, it must be marked with a package modifier. To grant access to other packages, it must be marked with a public modifier. Then you don't need a private to mean "this source file only" at all.

It seems like selective export like in Eiffel seems like it can only apply at the package level since methods are seperate from classes. E.g. package A could export symbols f, A, B.c to packages B and C. I am not sure how useful it is.

One important aspect is what the default visibilities should be. My preference is to make everything source-file-private by default. My second preference is to require a visibility modifier for every package-level construct.

-- BrianSmith - 04 Feb 2004

When defining visibility semantics is the assumption that they will apply to well behaved code or must they have runtime enforcement? The latter is likely preferable in real world applications yet may limit the semantics such that they can be implemented with those supplied by the JVM.

Note that Nice also has a form of capability security which is entirely missing from Java - local functions. Extending these to multidispatch LocalMethods? allows for methods private to the enclosing method or explicitly passed to outside parties. What forms of reflection on those method's environments should be allowed is a separate issue. It's almost like defining a method-based rather than class-based object system. Doesn't seem much scope for inheritance either, though functional composition...

-- RohanHart - 12 Jan 2005

 


VoidInTypesAndErrors  

14 Jan 2004 - 19:51 - NEW   IsaacGouy

void return types are allowed, and void can be used in anonymous functions. However ()-> still shows up in some error messages. Given the prevalence of C/Java would it be reasonable to consistently use void instead of (), and deprecate use of () ?

-- IsaacGouy - 14 Jan 2004

 


WebChanges  

16 Aug 2001 - 19:58 - NEW   PeterThoeny?

Topics in Dev web: Changed: now 16:11 GMT Changed by:
WebStatistics 14 Aug 2005 - 01:47 - r1.487 TWikiGuest
Statistics for Dev Web Month: Topic views: Topic saves: File uploads: Most popular topic views: Top contributors for topic save and uploads: Aug 2005 1736 0 0 116 ...  
UserManualOmissions 07 Jul 2005 - 10:05 - r1.43 DanielBonniot
These are aspects of the language that are not covered by the User Manual, but that should be. overview short paragraph giving the big information methods not contained ...  
StandardLibrary 02 Jul 2005 - 10:04 - r1.17 TWikiGuest
TOC Documentation for the standard library We need a documentation for the standard library. The best way would be to write a tool NiceDoc, similar to javadoc. There ...  
NiceConverter 23 Jun 2005 - 00:11 - NEW TWikiGuest
It would be nice to have a tool to convert a set of Java classes to Nice syntax (e.g. stripping out the typecasts, putting argument names in all method calls, etc ...  
FeatureProposals 23 Jun 2005 - 00:08 - r1.19 TWikiGuest
This page is where you can propose new features for Nice. page. You can also edit a feature page to comment on the proposal. PropertySyntax InnerClasses PartialApplicationSyntax ...  
TypeErasureLimitations 30 Apr 2005 - 12:14 - NEW TWikiGuest
Generics are implemented in Nice using a technique called `type erasure' just like in Java 5. The technique and some of its repercussions are quite nicely described ...  
NiceCompiler 30 Apr 2005 - 12:04 - r1.6 TWikiGuest
Implementation issues of the compiler. TodoList BadErrorMessages Documentation CompilationAPI SyntanticClassHierarchy CompilerTerminology TypeErasureLimitations Building ...  
EnhancedNullTesting 11 Apr 2005 - 14:50 - NEW TWikiGuest
http://sourceforge.net/tracker/index.php?func detail aid 671444 group id 12788 atid 362788 Section "Non-local variables" in http://nice.sourceforge.net/cgi-bin/twiki ...  
BootstrappingFromCVS 11 Apr 2005 - 12:48 - r1.3 TWikiGuest
Requirements: A proper javac for example the Sun or IBM ones. (not the gcj-wrapper) On Debian, for example use the `java-package' package Get the Nice module from ...  
DevelopmentVersion 06 Apr 2005 - 13:36 - r1.3 TWikiGuest
Before a new version is released, it is sometimes available for testing purposes. List of changes You can see the latest list of changes at http://cvs.sourceforge ...  
CheckedIntegerArithmetic 17 Jan 2005 - 20:08 - r1.12 MotiN
The current behaviour of numeric type is to silently overflow. In some cases this is what is needed, and in some cases you don't really care, because it is guaranteed ...  
EnumImplementation 16 Jan 2005 - 15:22 - r1.8 MotiN
Nice will get enums soon but first the exact implementation and syntax needs to be discussed. TOC Specification A good starting point is the java 1.5 enum proposal ...  
VisibilityModifiers 12 Jan 2005 - 03:16 - r1.15 RohanHart
What should be the exact semantics of the VisibilityModifiers? Can VisibilityModifiers added to method declarations or method implementations or both? How do VisibilityModifiers ...  
EclipsePlugin 10 Jan 2005 - 06:47 - r1.35 TWikiGuest
On this page the Nice Eclipse Plug-in is described TOC What is it? The "Nice Eclipse Plugin" is a plugin for the open source Eclipse IDE. It is possible to extend ...  
TreeDataConstruction 03 Jan 2005 - 00:09 - r1.6 MarkCC
An interresting idea from the Groovy language is to have an easy way to create tree like data as xml, html and user interfaces. More info: http://groovy.codehaus ...  
BigPictureWhatIsItGoodFor 22 Dec 2004 - 16:33 - r1.11 MikeBeckerle
Maybe a year from now, one of the most obvious special things about Nice will turn up in releases of Java and C# ( http://msdn.microsoft.com/msdnmag/issues/03/10 ...  
WebHome 20 Dec 2004 - 01:58 - r1.22 RohanHart
This is the place to discuss the ongoing development of Nice. FeatureProposals CurrentDiscussions NiceCompiler ToolsAndLibraries (includes EclipsePlugin...) DevelopmentVersion ...  
NewEclipsePlugin 03 Dec 2004 - 18:03 - NEW MartinGamsjaeger
As I am just starting to develop a new Eclipse Plugin for Nice, I wanted to share my first ideas and goals concerning features and their realization with the community ...  
ToolsAndLibraries 03 Dec 2004 - 17:56 - r1.10 MartinGamsjaeger
Current projects Doc.NiceSwing TestSuite EclipsePlugin NewEclipsePlugin Future projects (waiting for volunteers) NiceDoc NiceUnit syntax highlighting for vim update ...  
SyntanticClassHierarchy 18 Nov 2004 - 00:21 - r1.3 LucPerrin
In an attempt to understand better the syntax part of nice, here is the class hierarchy for the bossa.syntax package. I have included questions and comments for discussion ...  
CompilerTerminology 17 Nov 2004 - 19:15 - NEW ArjanB
Terms that may need explanation related to compilers and typesystems or terms that have specific meaning for Nice. General arity closure formalparameter Types monotype ...  
AnonymousExceptionHandling 21 Oct 2004 - 12:01 - NEW ImamTashdidUlAlam
I was just wondering, when Nice interacts heavily with Java, the resultant code contains too many curly braces which are not nice at all, as exceptions must be handled ...  
PackageRepository 23 Aug 2004 - 18:29 - r1.5 BrynKeller
This is a draft about how package repositories will be handled. Some motivation for this feature is given Doc.GetInvolved#The Community there . TOC Principle A repository ...  
JEditPlugin 05 Aug 2004 - 16:18 - NEW BrynKeller
I've started a JEdit syntax mode for Nice. Installation info and downloads are available from http://www.xoltar.org/2004/aug/05/jedit-nice-mode.html on my website ...  
AnnouncingNewReleases 29 Jul 2004 - 15:28 - r1.6 DanielBonniot
How and where to announce new releases? The release itself is done on sourceforge. It includes release notes and the changelog (copy-pasted from the http://cvs.sourceforge ...  
StreamTypes 23 Apr 2004 - 04:42 - r1.3 RohanHart
Erik Meijer and Wolfram Schulte have some interesting ideas about "stream types" which look like they could improve some of the code I've been writing. See http: ...  
HandlingJNI 20 Apr 2004 - 04:38 - NEW ChristianS
First some simple examples how JNI in JAVA works: Test.java: class Test { static { System.loadLibrary("test"); } public static void main(String args) { System.out ...  
CurrentDiscussions 20 Apr 2004 - 04:22 - r1.12 ChristianS
Discussions of the language aspects of Nice. StandardLibrary EnumImplementation VisibilityModifiers NiceConstructors ClassInvariants PatternSyntax SingletonClasses ...  
BlockCallSyntax 24 Feb 2004 - 19:08 - r1.16 BrynKeller
It would be good to allow a different syntax for method application in some circumstances. Specifically, it would be nice if: foo { baz(); } could expand into foo ...  
PartialApplicationSyntax 24 Feb 2004 - 18:11 - r1.14 IsaacGouy
Imported from SourceForge RFE #672069 Background: Many functional languages provide "curried" functions, of the form a b c, rather than the more typical (in Nice ...  
SyntaxChanges 14 Feb 2004 - 22:50 - r1.2 BrianSmith
A few syntax changes are being considered now. Using the same symbol for function types and anonymous functions. Making "val" an alternative for "let". "val" would ...  
ConstructorSyntax 09 Feb 2004 - 00:49 - r1.17 DanielBonniot
I'm trying to summarize my ideas on constructors, based on the NiceConstructors discussions we had. I think we should separate two aspects: creation of new instances ...  
CustomConstructors 05 Feb 2004 - 22:38 - r1.27 DanielBonniot
Construction is the process of creating a new object whose fields have some meaningful value. Currently, only the automaticly generated default constructor does that ...  
NiceConstructors 03 Feb 2004 - 09:42 - r1.35 DanielBonniot
Links to proposals UPDATE: As a first step, in the current development version, classes can have initializers, like in Java. One further improvement is to allow CustomConstructors ...  
BadErrorMessages 01 Feb 2004 - 20:23 - r1.12 DanielBonniot
An overview of error messages that needs improvement. TOC To do Unsatisfiable constraints class A{} class B extends A{} interface I{} class X implements I{}  
WebNotify 21 Jan 2004 - 03:31 - r1.9 BrianSmith
This is a subscription service to be automatically notified by e-mail when topics change in this Dev web. This is a convenient service, so you do not have to come ...  
VoidInTypesAndErrors 14 Jan 2004 - 19:51 - NEW IsaacGouy
void return types are allowed, and void can be used in anonymous functions. However ()- still shows up in some error messages. Given the prevalence of C/Java would ...  
TypeAlias 04 Jan 2004 - 22:04 - r1.4 ArjanB
Arjan has mentioned this a couple of times. Given that Nice is more than an OO language, do we need more than the ability to define a new object? (On a related subject ...  
ObjectType 15 Dec 2003 - 13:24 - r1.3 DanielBonniot
This page documents the support of the type Object in Nice, which has been present since version 0.9.5 Current Situation Object is currently a sort of alien in Nice ...  
AddingConstness 21 Nov 2003 - 07:40 - r1.4 BrianSlesinsky
On a longer term(post 1.0) Nice might get a const keyword. Anyone who's is interested in writing a proposal should look at this proposal for java: http://david.tribble ...  
DynamicMembers 17 Nov 2003 - 16:12 - r1.8 DanielBonniot
Dynamic Members This is the ability for a class to add members to their class at runtime. Actually, that's not what I'm proposing. I really want classes to be able ...  
PropertySyntax 12 Nov 2003 - 21:24 - r1.8 DanielBonniot
I was thinking if it maybe would be a good idea to let the compiler help when writing properties. What if we could let the compiler automatically create get/set functions ...  
UnknownType 12 Nov 2003 - 14:01 - r1.4 DanielBonniot
Unknown Type I'd like to propose something that, at first glance, goes against the strongly typed phylosophy of Nice and Java. I'd like to have the ability to sometimes ...  
PerformanceTesting 07 Nov 2003 - 12:10 - NEW DanielBonniot
We already have a comprehensive TestSuite, to check the correctness of the compiler. It would also be very useful to be able to automatically mesure performance. ...  
FunctionsReplacedByMultiMethods 18 Oct 2003 - 15:06 - r1.2 DanielBonniot
Note: this has been implemented, as of Nice 0.9.2 Main.DanielBonniot 18 Oct 2003 Imported email discussion: Could there be a way to also be able to separate the ...  
TodoList 18 Oct 2003 - 15:04 - r1.6 ArjanB
Overview of the things left to do in random order Features VisibilityModifiers. ChangeNumberOfTypeParametersInSubclasses PropertySyntax PartialApplicationSyntax Improved ...  
NiceDoc 13 Sep 2003 - 04:10 - r1.6 DanielBonniot
We need a javadoc-like tool for Nice. If possible, it would be good to re-use someone else's existing backends and just write a frontend for Nice. Main.BrynKeller ...  
InnerClasses 21 Aug 2003 - 19:47 - r1.3 ArjanB
I was wondering if it will sometime be possible to declare inner classes in Nice ? I guess this is very useful in some cases. Inner classes are currently not accepted ...  
ChangeNumberOfTypeParametersInSubclasses 08 Aug 2003 - 16:13 - r1.2 ArjanB
Does "Modification of the type system for subclasses with a different number of type parameters than the parent." mean that I could do: class B extends A {} rather ...  
StandardLibraryMethods 08 Aug 2003 - 15:47 - r1.3 ArjanB
An overview of the methods and function in stdlib for discussing semactics and as starting point of the documentation. The documentation comments are before the signatures ...  

Number of topics: 50

 


WebHome  

20 Dec 2004 - 01:58 - r1.22   RohanHart

This is the place to discuss the ongoing development of Nice.


TWiki.Dev Web:

 


WebIndex  

24 Nov 2001 - 11:41 - r1.2   PeterThoeny?

Topics in Dev web: Changed: now 16:11 GMT Changed by:
AddingConstness 21 Nov 2003 - 07:40 - r1.4 BrianSlesinsky
On a longer term(post 1.0) Nice might get a const keyword. Anyone who's is interested in writing a proposal should look at this proposal for java: http://david.tribble ...  
AnnouncingNewReleases 29 Jul 2004 - 15:28 - r1.6 DanielBonniot
How and where to announce new releases? The release itself is done on sourceforge. It includes release notes and the changelog (copy-pasted from the http://cvs.sourceforge ...  
AnonymousExceptionHandling 21 Oct 2004 - 12:01 - NEW ImamTashdidUlAlam
I was just wondering, when Nice interacts heavily with Java, the resultant code contains too many curly braces which are not nice at all, as exceptions must be handled ...  
AutomatedTests 22 Jun 2003 - 09:36 - NEW DanielBonniot
Tests are performed continuously to check that the compiler is working properly. The results are http://nice.sourceforge.net/tests.html published on the website . ...  
BadErrorMessages 01 Feb 2004 - 20:23 - r1.12 DanielBonniot
An overview of error messages that needs improvement. TOC To do Unsatisfiable constraints class A{} class B extends A{} interface I{} class X implements I{} void foo ...  
BigPictureWhatIsItGoodFor 22 Dec 2004 - 16:33 - r1.11 MikeBeckerle
Maybe a year from now, one of the most obvious special things about Nice will turn up in releases of Java and C# ( http://msdn.microsoft.com/msdnmag/issues/03/10/NET ...  
BlockCallSyntax 24 Feb 2004 - 19:08 - r1.16 BrynKeller
It would be good to allow a different syntax for method application in some circumstances. Specifically, it would be nice if: foo { baz(); } could expand into foo ...  
BootstrappingFromCVS 11 Apr 2005 - 12:48 - r1.3 TWikiGuest
Requirements: A proper javac for example the Sun or IBM ones. (not the gcj-wrapper) On Debian, for example use the `java-package' package Get the Nice module from ...  
ChangeNumberOfTypeParametersInSubclasses 08 Aug 2003 - 16:13 - r1.2 ArjanB
Does "Modification of the type system for subclasses with a different number of type parameters than the parent." mean that I could do: class B extends A {} rather ...  
CheckedIntegerArithmetic 17 Jan 2005 - 20:08 - r1.12 MotiN
The current behaviour of numeric type is to silently overflow. In some cases this is what is needed, and in some cases you don't really care, because it is guaranteed ...  
ClassInvariants 06 Jun 2003 - 18:48 - r1.4 DanielBonniot
I'm looking ahead to when invariants are added, and the crossover with NiceConstructors. Vague thoughts only, feel free to edit. There's an Eiffel hack to allow different ...  
CompilationAPI 18 Jun 2003 - 14:38 - NEW DanielBonniot
The compiler can be called from JVM languages (Nice, Java, ...) by using a high level API, instead of starting a different OS process (application). This is used by ...  
CompilerTerminology 17 Nov 2004 - 19:15 - NEW ArjanB
Terms that may need explanation related to compilers and typesystems or terms that have specific meaning for Nice. General arity closure formalparameter Types monotype ...  
ConstructorSyntax 09 Feb 2004 - 00:49 - r1.17 DanielBonniot
I'm trying to summarize my ideas on constructors, based on the NiceConstructors discussions we had. I think we should separate two aspects: creation of new instances ...  
CurrentDiscussions 20 Apr 2004 - 04:22 - r1.12 ChristianS
Discussions of the language aspects of Nice. StandardLibrary EnumImplementation VisibilityModifiers NiceConstructors ClassInvariants PatternSyntax SingletonClasses ...  
CustomConstructors 05 Feb 2004 - 22:38 - r1.27 DanielBonniot
Construction is the process of creating a new object whose fields have some meaningful value. Currently, only the automaticly generated default constructor does that ...  
DevelopmentVersion 06 Apr 2005 - 13:36 - r1.3 TWikiGuest
Before a new version is released, it is sometimes available for testing purposes. List of changes You can see the latest list of changes at http://cvs.sourceforge ...  
DynamicMembers 17 Nov 2003 - 16:12 - r1.8 DanielBonniot
Dynamic Members This is the ability for a class to add members to their class at runtime. Actually, that's not what I'm proposing. I really want classes to be able ...  
EclipsePlugin 10 Jan 2005 - 06:47 - r1.35 TWikiGuest
On this page the Nice Eclipse Plug-in is described TOC What is it? The "Nice Eclipse Plugin" is a plugin for the open source Eclipse IDE. It is possible to extend ...  
EnhancedNullTesting 11 Apr 2005 - 14:50 - NEW TWikiGuest
http://sourceforge.net/tracker/index.php?func detail aid 671444 group id 12788 atid 362788 Section "Non-local variables" in http://nice.sourceforge.net/cgi-bin/twiki ...  
EnumImplementation 16 Jan 2005 - 15:22 - r1.8 MotiN
Nice will get enums soon but first the exact implementation and syntax needs to be discussed. TOC Specification A good starting point is the java 1.5 enum proposal ...  
FeatureProposals 23 Jun 2005 - 00:08 - r1.19 TWikiGuest
This page is where you can propose new features for Nice. page. You can also edit a feature page to comment on the proposal. PropertySyntax InnerClasses PartialApplicationSyntax ...  
FieldTypeOverriding 02 Aug 2003 - 08:24 - r1.2 DanielBonniot
It is often useful to declare that, in a subclass, a certain field of the superclass has a more precise type. To be safe, this feature only applies to final fields ...  
FlagInterfaces 06 Jun 2003 - 19:17 - r1.7 DanielBonniot
This page shows the concept of FlagInterfaces to solve the typesafety problem of the collections api. Note: this is an immature proposal and the syntax will change ...  
FunctionsReplacedByMultiMethods 18 Oct 2003 - 15:06 - r1.2 DanielBonniot
Note: this has been implemented, as of Nice 0.9.2 Main.DanielBonniot 18 Oct 2003 Imported email discussion: Could there be a way to also be able to separate the ...  
HandlingJNI 20 Apr 2004 - 04:38 - NEW ChristianS
First some simple examples how JNI in JAVA works: Test.java: class Test { static { System.loadLibrary("test"); } public static void main(String args) { System.out ...  
InnerClasses 21 Aug 2003 - 19:47 - r1.3 ArjanB
I was wondering if it will sometime be possible to declare inner classes in Nice ? I guess this is very useful in some cases. Inner classes are currently not accepted ...  
JEditPlugin 05 Aug 2004 - 16:18 - NEW BrynKeller
I've started a JEdit syntax mode for Nice. Installation info and downloads are available from http://www.xoltar.org/2004/aug/05/jedit-nice-mode.html on my website ...  
NewEclipsePlugin 03 Dec 2004 - 18:03 - NEW MartinGamsjaeger
As I am just starting to develop a new Eclipse Plugin for Nice, I wanted to share my first ideas and goals concerning features and their realization with the community ...  
NiceCasts 06 Jun 2003 - 20:26 - r1.24 AlexGreif
Here are some examples where I had to use cast or notNull in my project. BR Which problems are not solved yet in 0.8? Main.ArjanB java.util.List handles new ArrayList ...  
NiceCompiler 30 Apr 2005 - 12:04 - r1.6 TWikiGuest
Implementation issues of the compiler. TodoList BadErrorMessages Documentation CompilationAPI SyntanticClassHierarchy CompilerTerminology TypeErasureLimitations Building ...  
NiceCompilerInNice 12 Jun 2003 - 10:37 - NEW ArjanB
When and how should the NiceCompiler(bossa. packages) be converted to Nice? It has quite a few benefits but it will require a lot of time to do so. Is the language ...  
NiceConstructors 03 Feb 2004 - 09:42 - r1.35 DanielBonniot
Links to proposals UPDATE: As a first step, in the current development version, classes can have initializers, like in Java. One further improvement is to allow CustomConstructors ...  
NiceConverter 23 Jun 2005 - 00:11 - NEW TWikiGuest
It would be nice to have a tool to convert a set of Java classes to Nice syntax (e.g. stripping out the typecasts, putting argument names in all method calls, etc ...  
NiceDoc 13 Sep 2003 - 04:10 - r1.6 DanielBonniot
We need a javadoc-like tool for Nice. If possible, it would be good to re-use someone else's existing backends and just write a frontend for Nice. Main.BrynKeller ...  
NiceLogos 02 Aug 2003 - 09:22 - r1.5 DanielBonniot
Very Nice: mailto:subagsol@yahoo.com Chetan Mittal Nice Logo for Eclipse-Plugin: mailto:subagsol@yahoo.com Chetan Mittal Nice work! It might be good to keep some ...  
ObjectType 15 Dec 2003 - 13:24 - r1.3 DanielBonniot
This page documents the support of the type Object in Nice, which has been present since version 0.9.5 Current Situation Object is currently a sort of alien in Nice ...  
PackageRepository 23 Aug 2004 - 18:29 - r1.5 BrynKeller
This is a draft about how package repositories will be handled. Some motivation for this feature is given Doc.GetInvolved#The Community there . TOC Principle A repository ...  
ParserCombinators 25 Apr 2003 - 18:44 - NEW BrynKeller
Parser combinators are a functional approach to parsing that uses a combination of functions to define the grammar. Some (like me) find that this leads to a pleasantly ...  
PartialApplicationSyntax 24 Feb 2004 - 18:11 - r1.14 IsaacGouy
Imported from SourceForge RFE #672069 Background: Many functional languages provide "curried" functions, of the form a b c, rather than the more typical (in Nice ...  
PerformanceTesting 07 Nov 2003 - 12:10 - NEW DanielBonniot
We already have a comprehensive TestSuite, to check the correctness of the compiler. It would also be very useful to be able to automatically mesure performance. This ...  
PropertySyntax 12 Nov 2003 - 21:24 - r1.8 DanielBonniot
I was thinking if it maybe would be a good idea to let the compiler help when writing properties. What if we could let the compiler automatically create get/set functions ...  
StandardLibrary 02 Jul 2005 - 10:04 - r1.17 TWikiGuest
TOC Documentation for the standard library We need a documentation for the standard library. The best way would be to write a tool NiceDoc, similar to javadoc. There ...  
StandardLibraryMethods 08 Aug 2003 - 15:47 - r1.3 ArjanB
An overview of the methods and function in stdlib for discussing semactics and as starting point of the documentation. The documentation comments are before the signatures ...  
StreamTypes 23 Apr 2004 - 04:42 - r1.3 RohanHart
Erik Meijer and Wolfram Schulte have some interesting ideas about "stream types" which look like they could improve some of the code I've been writing. See http:/ ...  
SuperCall 11 Apr 2003 - 22:01 - r1.3 DanielBonniot
This page documents the current super mechanism in Nice. It compares it with super in Java, and calls for discussion on ehancements. First, it does not make sense ...  
SyntanticClassHierarchy 18 Nov 2004 - 00:21 - r1.3 LucPerrin
In an attempt to understand better the syntax part of nice, here is the class hierarchy for the bossa.syntax package. I have included questions and comments for discussion ...  
SyntaxChanges 14 Feb 2004 - 22:50 - r1.2 BrianSmith
A few syntax changes are being considered now. Using the same symbol for function types and anonymous functions. Making "val" an alternative for "let". "val" would ...  
TestMachine 22 Jun 2003 - 10:03 - r1.5 DanielBonniot
A TestMachine is a machine that runs the AutomatedTests for Nice. This page documents how to set up a new TestMachine. TOC Requirements To be most useful, the tests ...  
TestSuite 02 Aug 2003 - 15:40 - r1.5 DanielBonniot
This page documents the testsuite engine for Nice. It also contains a list of wanted features that are not implemented yet. TOC Nice TestSuite Documentation The Nice ...  
TodoList 18 Oct 2003 - 15:04 - r1.6 ArjanB
Overview of the things left to do in random order Features VisibilityModifiers. ChangeNumberOfTypeParametersInSubclasses PropertySyntax PartialApplicationSyntax Improved ...  
ToolsAndLibraries 03 Dec 2004 - 17:56 - r1.10 MartinGamsjaeger
Current projects Doc.NiceSwing TestSuite EclipsePlugin NewEclipsePlugin Future projects (waiting for volunteers) NiceDoc NiceUnit syntax highlighting for vim update ...  
TreeDataConstruction 03 Jan 2005 - 00:09 - r1.6 MarkCC
An interresting idea from the Groovy language is to have an easy way to create tree like data as xml, html and user interfaces. More info: http://groovy.codehaus.org ...  
TupleFunctionDeclaration 18 Jun 2003 - 18:07 - r1.3 DanielBonniot
This page describes the feature request to use tuple types in function declarations and anonymous functions. The following code shows the currently working way. The ...  
TypeAlias 04 Jan 2004 - 22:04 - r1.4 ArjanB
Arjan has mentioned this a couple of times. Given that Nice is more than an OO language, do we need more than the ability to define a new object? (On a related subject ...  
TypeErasureLimitations 30 Apr 2005 - 12:14 - NEW TWikiGuest
Generics are implemented in Nice using a technique called `type erasure' just like in Java 5. The technique and some of its repercussions are quite nicely described ...  
UnknownType 12 Nov 2003 - 14:01 - r1.4 DanielBonniot
Unknown Type I'd like to propose something that, at first glance, goes against the strongly typed phylosophy of Nice and Java. I'd like to have the ability to sometimes ...  
UserManualOmissions 07 Jul 2005 - 10:05 - r1.43 DanielBonniot
These are aspects of the language that are not covered by the User Manual, but that should be. overview short paragraph giving the big information methods not contained ...  
VisibilityModifiers 12 Jan 2005 - 03:16 - r1.15 RohanHart
What should be the exact semantics of the VisibilityModifiers? Can VisibilityModifiers added to method declarations or method implementations or both? How do VisibilityModifiers ...  
VoidInTypesAndErrors 14 Jan 2004 - 19:51 - NEW IsaacGouy
void return types are allowed, and void can be used in anonymous functions. However ()- still shows up in some error messages. Given the prevalence of C/Java would ...  
WebChanges 16 Aug 2001 - 19:58 - NEW PeterThoeny?
INCLUDE{" TWIKIWEB .WebChanges"}  
WebHome 20 Dec 2004 - 01:58 - r1.22 RohanHart
This is the place to discuss the ongoing development of Nice. FeatureProposals CurrentDiscussions NiceCompiler ToolsAndLibraries (includes EclipsePlugin...) DevelopmentVersion ...  
WebIndex 24 Nov 2001 - 11:41 - r1.2 PeterThoeny?
SEARCH{"\. " scope "topic" regex "on" nosearch "on"} See also the faster WebTopicList  
WebNotify 21 Jan 2004 - 03:31 - r1.9 BrianSmith
This is a subscription service to be automatically notified by e-mail when topics change in this Dev web. This is a convenient service, so you do not have to come ...  
WebPreferences 06 Mar 2003 - 16:56 - r1.4 AlexGreif
TWiki.Dev Web Preferences The following settings are web preferences of the TWiki.Dev web. These preferences overwrite the site-level preferences in TWIKIWEB . WIKIPREFSTOPIC ...  
WebRss 30 Jan 2003 - 08:15 - NEW PeterThoeny?
TWiki's Dev web SCRIPTURL /view SCRIPTSUFFIX /Dev The Dev web of TWiki. TWiki is a Web-Based Collaboration Platform for the Corporate World. INCLUDE{" TWIKIWEB .WebRssBase ...  
WebSearch 08 Aug 2001 - 05:26 - NEW PeterThoeny?
INCLUDE{" TWIKIWEB .WebSearch"}  
WebStatistics 14 Aug 2005 - 01:47 - r1.487 TWikiGuest
Statistics for Dev Web Month: Topic views: Topic saves: File uploads: Most popular topic views: Top contributors for topic save and uploads: Aug 2005 1736 0 0 116 ...  
WebTopicList 24 Nov 2001 - 11:40 - NEW PeterThoeny?
TOPICLIST{" $name "} See also the verbose WebIndex.  
WritingAutomatedTests 22 Jun 2003 - 10:06 - NEW DanielBonniot
Generalities A test is a procedure that checks some functionality of the Nice compiler. Format Each test consists of an executable file. It must be placed in the ...  

Number of topics: 70

See also the faster WebTopicList

 


WebNotify  

21 Jan 2004 - 03:31 - r1.9   BrianSmith

This is a subscription service to be automatically notified by e-mail when topics change in this Dev web. This is a convenient service, so you do not have to come back and check all the time if something has changed. To subscribe, please add a bullet with your WikiName in alphabetical order to this list:

Format: <space><space><space>, followed by:
* Main.yourWikiName (if you want that the e-mail address in your home page is used)
* Main.yourWikiName - yourEmailAddress (if you want to specify a different e-mail address)
* Main.anyTWikiGroup (if you want to notify all members of a particular TWikiGroup)

Related topics: TWikiUsers, TWikiRegistration

 


WebPreferences  

06 Mar 2003 - 16:56 - r1.4   AlexGreif

TWiki.Dev Web Preferences

The following settings are web preferences of the TWiki.Dev web. These preferences overwrite the site-level preferences in TWikiPreferences, and can be overwritten by user preferences (your personal topic, i.e. TWikiGuest in the TWiki.Main web)

Preferences:

Notes:

Related Topics:

 


WebRss  

30 Jan 2003 - 08:15 - NEW   PeterThoeny?

TWiki's Dev web http://nice.sourceforge.net/cgi-bin/twiki/view/Dev The Dev web of TWiki. TWiki is a Web-Based Collaboration Platform for the Corporate World. en-us Copyright 2009, Peter Thoeny and contributing authors. Peter Thoeny [Peter@Thoeny.com] Peter Thoeny [Peter@Thoeny.com] TWiki TWiki.Dev TWiki.Dev http://nice.sourceforge.net/cgi-bin/twiki/view/Dev http://nice.sourceforge.net/twiki/pub/TWiki/TWikiLogos/twikilogo88x31.gif WebStatistics http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/WebStatistics Statistics for Dev Web Month: Topic views: Topic saves: File uploads: Most popular topic views: Top contributors for topic save and uploads: Aug 2005 1736 0 0 116 ... 2005-08-14T01:47:00Z guest 1.487 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/WebStatistics http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/WebStatistics UserManualOmissions http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/UserManualOmissions These are aspects of the language that are not covered by the User Manual, but that should be. overview short paragraph giving the big information methods not contained ... 2005-07-07T10:05:00Z DanielBonniot 1.43 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/UserManualOmissions http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/UserManualOmissions StandardLibrary http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/StandardLibrary TOC Documentation for the standard library We need a documentation for the standard library. The best way would be to write a tool NiceDoc, similar to javadoc. There ... 2005-07-02T10:04:00Z guest 1.17 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/StandardLibrary http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/StandardLibrary NiceConverter http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/NiceConverter It would be nice to have a tool to convert a set of Java classes to Nice syntax (e.g. stripping out the typecasts, putting argument names in all method calls, etc ... 2005-06-23T00:11:00Z guest 1.1 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/NiceConverter http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/NiceConverter FeatureProposals http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/FeatureProposals This page is where you can propose new features for Nice. page. You can also edit a feature page to comment on the proposal. PropertySyntax InnerClasses PartialApplicationSyntax ... 2005-06-23T00:08:00Z guest 1.19 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/FeatureProposals http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/FeatureProposals TypeErasureLimitations http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/TypeErasureLimitations Generics are implemented in Nice using a technique called `type erasure' just like in Java 5. The technique and some of its repercussions are quite nicely described ... 2005-04-30T12:14:00Z guest 1.1 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/TypeErasureLimitations http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/TypeErasureLimitations NiceCompiler http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/NiceCompiler Implementation issues of the compiler. TodoList BadErrorMessages Documentation CompilationAPI SyntanticClassHierarchy CompilerTerminology TypeErasureLimitations Building ... 2005-04-30T12:04:00Z guest 1.6 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/NiceCompiler http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/NiceCompiler EnhancedNullTesting http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/EnhancedNullTesting http://sourceforge.net/tracker/index.php?func detail aid 671444 group id 12788 atid 362788 Section "Non-local variables" in http://nice.sourceforge.net/cgi-bin/twiki ... 2005-04-11T14:50:00Z guest 1.1 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/EnhancedNullTesting http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/EnhancedNullTesting BootstrappingFromCVS http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/BootstrappingFromCVS Requirements: A proper javac for example the Sun or IBM ones. (not the gcj-wrapper) On Debian, for example use the `java-package' package Get the Nice module from ... 2005-04-11T12:48:00Z guest 1.3 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/BootstrappingFromCVS http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/BootstrappingFromCVS DevelopmentVersion http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/DevelopmentVersion Before a new version is released, it is sometimes available for testing purposes. List of changes You can see the latest list of changes at http://cvs.sourceforge ... 2005-04-06T13:36:00Z guest 1.3 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/DevelopmentVersion http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/DevelopmentVersion CheckedIntegerArithmetic http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/CheckedIntegerArithmetic The current behaviour of numeric type is to silently overflow. In some cases this is what is needed, and in some cases you don't really care, because it is guaranteed ... 2005-01-17T20:08:00Z MotiN 1.12 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/CheckedIntegerArithmetic http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/CheckedIntegerArithmetic EnumImplementation http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/EnumImplementation Nice will get enums soon but first the exact implementation and syntax needs to be discussed. TOC Specification A good starting point is the java 1.5 enum proposal ... 2005-01-16T15:22:00Z MotiN 1.8 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/EnumImplementation http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/EnumImplementation VisibilityModifiers http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/VisibilityModifiers What should be the exact semantics of the VisibilityModifiers? Can VisibilityModifiers added to method declarations or method implementations or both? How do VisibilityModifiers ... 2005-01-12T03:16:00Z RohanHart 1.15 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/VisibilityModifiers http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/VisibilityModifiers EclipsePlugin http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/EclipsePlugin On this page the Nice Eclipse Plug-in is described TOC What is it? The "Nice Eclipse Plugin" is a plugin for the open source Eclipse IDE. It is possible to extend ... 2005-01-10T06:47:00Z guest 1.35 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/EclipsePlugin http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/EclipsePlugin TreeDataConstruction http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/TreeDataConstruction An interresting idea from the Groovy language is to have an easy way to create tree like data as xml, html and user interfaces. More info: http://groovy.codehaus.org ... 2005-01-03T00:09:00Z MarkCC 1.6 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/TreeDataConstruction http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/TreeDataConstruction BigPictureWhatIsItGoodFor http://nice.sourceforge.net/cgi-bin/twiki/view/Dev/BigPictureWhatIsItGoodFor Maybe a year from now, one of the most obvious special things about Nice will turn up in releases of Java and C# ( http://msdn.microsoft.com/msdnmag/issues/03/10/NET ... 2004-12-22T16:33:00Z MikeBeckerle 1.11 updated major http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/BigPictureWhatIsItGoodFor http://nice.sourceforge.net/cgi-bin/twiki/rdiff/Dev/BigPictureWhatIsItGoodFor

 


WebSearch  

08 Aug 2001 - 05:26 - NEW   PeterThoeny?

 


WebStatistics  

14 Aug 2005 - 01:47 - r1.487   TWikiGuest

Statistics for Dev Web

Month: Topic
views:
Topic
saves:
File
uploads:
Most popular
topic views:
Top contributors for
topic save and uploads:
Aug 2005 1736 0 0 116 NiceConstructors
102 WebHome
100 EclipsePlugin
 77 CustomConstructors
 62 UserManualOmissions
 61 VisibilityModifiers
 59 ConstructorSyntax
 51 NiceCasts
 40 FeatureProposals
 39 StandardLibrary
 38 CurrentDiscussions
 
Jul 2005 3496 2 0 236 EclipsePlugin
222 WebHome
183 NiceConstructors
165 WebStatistics
119 VisibilityModifiers
118 UserManualOmissions
114 CustomConstructors
102 StandardLibrary
 96 FeatureProposals
 81 NiceCasts
 75 ConstructorSyntax
  1 TWikiGuest
  1 DanielBonniot
Jun 2005 8875 2 0 2988 WebStatistics
420 EclipsePlugin
356 WebHome
322 UserManualOmissions
288 NiceConstructors
217 CustomConstructors
210 NiceCasts
203 FeatureProposals
164 StandardLibrary
156 VisibilityModifiers
147 BlockCallSyntax
  2 TWikiGuest
May 2005 2227 0 0 175 WebHome
143 WebStatistics
123 EclipsePlugin
101 UserManualOmissions
 70 NiceCasts
 63 FeatureProposals
 58 ConstructorSyntax
 56 NiceConstructors
 53 CurrentDiscussions
 53 BigPictureWhatIsItGoodFor
 47 StandardLibrary
 
Apr 2005 2236 9 0 180 WebStatistics
171 WebHome
146 EclipsePlugin
129 NiceConstructors
 84 StandardLibrary
 63 VisibilityModifiers
 60 UserManualOmissions
 57 CurrentDiscussions
 51 FeatureProposals
 50 AnnouncingNewReleases
 49 ToolsAndLibraries
  9 TWikiGuest
Mar 2005 5687 0 0 1165 WebStatistics
354 WebHome
334 EclipsePlugin
200 UserManualOmissions
197 NiceConstructors
134 FeatureProposals
130 StandardLibrary
126 NiceCasts
118 CustomConstructors
111 VisibilityModifiers
104 CurrentDiscussions
 
Feb 2005 3053 0 0 302 WebStatistics
256 WebHome
209 EclipsePlugin
115 UserManualOmissions
107 NiceConstructors
 84 FeatureProposals
 82 CustomConstructors
 79 StandardLibrary
 73 NiceCasts
 65 CurrentDiscussions
 64 ToolsAndLibraries
 
Jan 2005 3153 9 0 329 WebStatistics
261 WebHome
163 EclipsePlugin
101 UserManualOmissions
 98 WebChanges
 88 FeatureProposals
 85 NiceConstructors
 84 EnumImplementation
 83 NiceCasts
 80 VisibilityModifiers
 77 CheckedIntegerArithmetic
  4 MotiN
  2 RohanHart
  2 MarkCC
  1 TWikiGuest
Dec 2004 1975 8 0 204 WebHome
161 EclipsePlugin
150 WebStatistics
 81 WebChanges
 71 NiceConstructors
 58 StandardLibrary
 57 UserManualOmissions
 55 FeatureProposals
 52 ToolsAndLibraries
 48 VisibilityModifiers
 48 NewEclipsePlugin
  5 MartinGamsjaeger
  1 TWikiGuest
  1 RohanHart
  1 MikeBeckerle
Nov 2004 4376 8 0 896 WebStatistics
346 WebHome
198 EclipsePlugin
145 NiceConstructors
136 WebChanges
134 UserManualOmissions
114 FeatureProposals
 94 StandardLibrary
 90 NiceCasts
 87 CurrentDiscussions
 85 VisibilityModifiers
  4 ArjanB
  3 LucPerrin
  1 UserUser
Oct 2004 6010 2 0 1740 WebStatistics
361 WebHome
278 EclipsePlugin
219 UserManualOmissions
218 NiceConstructors
153 FeatureProposals
139 NiceCasts
135 CustomConstructors
124 WebChanges
115 CurrentDiscussions
114 StandardLibrary
  2 ImamTashdidUlAlam
Sep 2004 1413 1 0 148 WebHome
132 WebChanges
118 WebStatistics
 87 EclipsePlugin
 53 NiceConstructors
 37 FeatureProposals
 34 NiceLogos
 33 ToolsAndLibraries
 31 UserManualOmissions
 31 AnnouncingNewReleases
 30 CurrentDiscussions
  1 ArjanB
Aug 2004 5264 8 0 1492 WebStatistics
422 NiceConstructors
304 WebHome
202 EclipsePlugin
148 UserManualOmissions
125 WebChanges
102 FeatureProposals
100 NiceCasts
100 CurrentDiscussions
 92 VisibilityModifiers
 85 CustomConstructors
  4 DanielBonniot
  3 BrynKeller
  1 ArjanB
Jul 2004 897 0 0 106 WebHome
 91 EclipsePlugin
 39 WebStatistics
 34 WebChanges
 29 FeatureProposals
 29 BigPictureWhatIsItGoodFor
 28 CurrentDiscussions
 25 NiceConstructors
 23 DevelopmentVersion
 22 EnumImplementation
 18 ToolsAndLibraries
 
Jun 2004 3026 0 0 432 WebStatistics
239 WebHome
167 EclipsePlugin
110 UserManualOmissions
105 CurrentDiscussions
 98 NiceConstructors
 91 FeatureProposals
 85 WebChanges
 83 NiceCasts
 69 StandardLibrary
 63 BigPictureWhatIsItGoodFor
 
May 2004 1690 0 0 164 WebHome
115 WebChanges
 80 NiceConstructors
 70 EclipsePlugin
 69 FeatureProposals
 56 CurrentDiscussions
 48 EnumImplementation
 47 UserManualOmissions
 47 StandardLibrary
 46 CustomConstructors
 38 WebStatistics
 
Apr 2004 7146 7 0 1790 WebStatistics
353 WebHome
311 UserManualOmissions
277 EclipsePlugin
262 NiceConstructors
209 WebChanges
175 CustomConstructors
173 NiceCasts
159 FeatureProposals
151 StandardLibrary
147 CurrentDiscussions
  3 RohanHart
  2 ChristianS
  2 BrynKeller
Mar 2004 4973 2 0 424 WebHome
214 WebChanges
207 EclipsePlugin
162 UserManualOmissions
149 WebStatistics
148 NiceCasts
146 NiceConstructors
143 FeatureProposals
126 VisibilityModifiers
122 CurrentDiscussions
121 StandardLibrary
  1 DanielBonniot
  1 ArjanB
Feb 2004 5271 61 0 925 WebStatistics
568 WebChanges
314 WebHome
247 UserManualOmissions
212 NiceConstructors
210 EclipsePlugin
169 CustomConstructors
130 FeatureProposals
124 NiceCasts
121 BlockCallSyntax
117 VisibilityModifiers
 19 DanielBonniot
 16 IsaacGouy
 15 BrianSmith
  9 BrynKeller
  2 ArjanB
Jan 2004 4551 82 0 740 WebChanges
337 WebStatistics
292 WebHome
178 EclipsePlugin
170 UserManualOmissions
169 NiceConstructors
168 CustomConstructors
158 FeatureProposals
132 PartialApplicationSyntax
100 NiceCasts
 94 CurrentDiscussions
 25 IsaacGouy
 19 DanielBonniot
 18 BrianSmith
 18 ArjanB
  2 BrynKeller
Dec 2003 2631 42 0 401 WebChanges
243 WebHome
168 EclipsePlugin
 96 NiceConstructors
 90 FeatureProposals
 78 UserManualOmissions
 77 ToolsAndLibraries
 75 WebStatistics
 74 NiceCasts
 72 StandardLibrary
 71 BigPictureWhatIsItGoodFor
 20 DanielBonniot
  6 IsaacGouy
  6 ArjanB
  5 BrianSlesinsky
  4 BrynKeller
  1 TWikiGuest
Nov 2003 3016 23 0 333 WebStatistics
250 WebChanges
230 WebHome
168 EclipsePlugin
126 NiceConstructors
106 FeatureProposals
 98 VisibilityModifiers
 72 DynamicMembers
 71 NiceCasts
 69 PropertySyntax
 65 StandardLibrary
  9 TroyHeninger
  9 DanielBonniot
  2 BrianSlesinsky
  1 RohanHart
  1 BrynKeller
  1 ArjanB
Oct 2003 1839 29 0 276 WebChanges
202 WebHome
147 EclipsePlugin
 99 WebStatistics
 95 NiceConstructors
 63 FeatureProposals
 62 BigPictureWhatIsItGoodFor
 48 UserManualOmissions
 47 VisibilityModifiers
 47 CurrentDiscussions
 38 StandardLibrary
  9 DanielBonniot
  6 IsaacGouy
  6 BrynKeller
  5 ArjanB
  3 TroyHeninger
Sep 2003 2067 15 0 204 WebHome
187 EclipsePlugin
159 WebChanges
105 WebStatistics
103 NiceCasts
 88 NiceConstructors
 57 VisibilityModifiers
 57 StandardLibrary
 55 FeatureProposals
 52 PropertySyntax
 52 CurrentDiscussions
  6 IsaacGouy
  3 DanielBonniot
  3 AlexGreif
  2 ArjanB
  1 BrynKeller
Aug 2003 2565 35 0 273 WebHome
254 WebChanges
210 EclipsePlugin
123 NiceConstructors
107 NiceCasts
 90 WebStatistics
 90 FeatureProposals
 85 StandardLibrary
 77 CurrentDiscussions
 72 ToolsAndLibraries
 63 VisibilityModifiers
 15 DanielBonniot
 12 ArjanB
  2 TWikiGuest
  2 RohanHart
  2 AlexGreif
  1 JohnBMesserly
  1 IsaacGouy
Jul 2003 2778 6 0 306 WebChanges
256 WebHome
226 WebStatistics
195 EclipsePlugin
142 NiceCasts
125 NiceConstructors
107 StandardLibrary
 99 CurrentDiscussions
 89 FeatureProposals
 84 BadErrorMessages
 76 EnumImplementation
  5 DanielBonniot
  1 ArjanB
Jun 2003 2207 109 1 691 WebChanges
273 WebHome
179 EclipsePlugin
136 WebStatistics
100 NiceConstructors
 86 StandardLibrary
 61 NiceCasts
 60 CurrentDiscussions
 35 FeatureProposals
 34 VisibilityModifiers
 34 NiceCompiler
 56 DanielBonniot
 31 AlexGreif
 14 ArjanB
  5 BrynKeller
  4 DavidJeske
May 2003 1187 25 0 283 WebChanges
189 WebHome
 90 NiceConstructors
 57 NiceDiscussions?
 51 FeatureProposals
 45 WebStatistics
 34 NiceProjects?
 31 ClassInvariants
 28 DevelopmentVersion
 27 VisibilityModifiers
 25 TestMachine
 10 DanielBonniot
  6 ArjanB
  5 SamsonDeJ
  3 BrynKeller
  1 TWikiGuest
Apr 2003 1564 72 0 386 WebChanges
268 WebHome
 92 NiceCasts
 86 WebStatistics
 60 FeatureProposals
 58 PropertySyntax
 46 NiceProjects?
 39 WebNotify
 37 NiceCompiler
 37 FlagInterfaces
 36 SuperCall
 27 DanielBonniot
 22 ArjanB
 15 AlexGreif
  5 BrynKeller
  3 ArthurSmyles
Mar 2003 919 11 0 220 WebHome
 84 WebStatistics
 71 FeatureProposals
 62 NiceProjects?
 48 WebChanges
 44 TestSuite
 40 WebNotify
 39 PropertySyntax
 34 FunctionsReplacedByMultiMethods
 32 DevelopmentVersion
 31 PartialApplicationSyntax
  5 AlexGreif
  3 ArjanB
  2 TWikiGuest
  1 DanielBonniot

Notes:

 


WebTopicList  

24 Nov 2001 - 11:40 - NEW   PeterThoeny?

See also the verbose WebIndex.

 


WritingAutomatedTests  

22 Jun 2003 - 10:06 - NEW   DanielBonniot

Generalities

A test is a procedure that checks some functionality of the Nice compiler.

Format

Each test consists of an executable file. It must be placed in the toplevel directory of the framework. The file name must be of the form: .test Most likely, it will consist of a shell script, that drives the compilation of some code, and returns an exit code to report how it went.

Variables

The script can use the following environment variables:

Exit codes

Output

The test script should output on standard out detailed information about the execution of the test. This output will be stored, and can be used to diagnose why a test failed.

-- DanielBonniot - 22 Jun 2003

 



Number of topics: 70

Topic WebHome . { }
  Copyright © 1999-2003 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Ideas, requests, problems regarding TWiki? Send feedback.